├── .gitignore ├── LICENSE ├── README.md ├── config └── checkstyle │ └── checkstyle.xml ├── pom.xml └── src ├── main ├── java │ ├── jdk │ │ └── incubator │ │ │ └── sql2 │ │ │ ├── AdbaDataSourceProperty.java │ │ │ ├── AdbaSessionProperty.java │ │ │ ├── AdbaType.java │ │ │ ├── ArrayRowCountOperation.java │ │ │ ├── DataSource.java │ │ │ ├── DataSourceFactory.java │ │ │ ├── DataSourceProperty.java │ │ │ ├── Examples.java │ │ │ ├── LocalOperation.java │ │ │ ├── MultiOperation.java │ │ │ ├── Operation.java │ │ │ ├── OperationGroup.java │ │ │ ├── OutOperation.java │ │ │ ├── ParameterizedOperation.java │ │ │ ├── ParameterizedRowCountOperation.java │ │ │ ├── ParameterizedRowOperation.java │ │ │ ├── ParameterizedRowPublisherOperation.java │ │ │ ├── PrimitiveOperation.java │ │ │ ├── Result.java │ │ │ ├── RowCountOperation.java │ │ │ ├── RowOperation.java │ │ │ ├── RowPublisherOperation.java │ │ │ ├── Session.java │ │ │ ├── SessionProperty.java │ │ │ ├── ShardingKey.java │ │ │ ├── SqlArray.java │ │ │ ├── SqlBlob.java │ │ │ ├── SqlClob.java │ │ │ ├── SqlColumns.java │ │ │ ├── SqlException.java │ │ │ ├── SqlParameter.java │ │ │ ├── SqlRef.java │ │ │ ├── SqlSkippedException.java │ │ │ ├── SqlStruct.java │ │ │ ├── SqlType.java │ │ │ ├── Submission.java │ │ │ ├── TransactionCompletion.java │ │ │ ├── TransactionOutcome.java │ │ │ └── package-info.java │ ├── module-info.java │ └── org │ │ └── postgresql │ │ └── adba │ │ ├── PgDataSource.java │ │ ├── PgDataSourceBuilder.java │ │ ├── PgDataSourceFactory.java │ │ ├── PgDataSourceProperty.java │ │ ├── PgSession.java │ │ ├── PgSessionBuilder.java │ │ ├── PgSessionDbProperty.java │ │ ├── PgSessionProperty.java │ │ ├── PgSubmission.java │ │ ├── buffer │ │ ├── ByteBufferPool.java │ │ ├── ByteBufferPoolOutputStream.java │ │ ├── DefaultByteBufferPool.java │ │ └── PooledByteBuffer.java │ │ ├── communication │ │ ├── BeFrame.java │ │ ├── BeFrameParser.java │ │ ├── FrontendTag.java │ │ ├── NetworkConnect.java │ │ ├── NetworkConnectContext.java │ │ ├── NetworkConnection.java │ │ ├── NetworkContext.java │ │ ├── NetworkErrorHandler.java │ │ ├── NetworkOutputStream.java │ │ ├── NetworkReadContext.java │ │ ├── NetworkRequest.java │ │ ├── NetworkResponse.java │ │ ├── NetworkWriteContext.java │ │ ├── PreparedStatementCache.java │ │ ├── ProtocolV3States.java │ │ ├── TableCell.java │ │ ├── network │ │ │ ├── AbstractPortalResponse.java │ │ │ ├── AuthenticationResponse.java │ │ │ ├── BindRequest.java │ │ │ ├── BindResponse.java │ │ │ ├── CloseRequest.java │ │ │ ├── CloseResponse.java │ │ │ ├── DescribeRequest.java │ │ │ ├── DescribeResponse.java │ │ │ ├── ExecuteRequest.java │ │ │ ├── ExecuteResponse.java │ │ │ ├── ImmediateComplete.java │ │ │ ├── Md5PasswordRequest.java │ │ │ ├── NetworkConnectRequest.java │ │ │ ├── ParseRequest.java │ │ │ ├── ParseResponse.java │ │ │ ├── Portal.java │ │ │ ├── Query.java │ │ │ ├── ReadyForQueryResponse.java │ │ │ ├── SaslCompleteResponse.java │ │ │ ├── SaslContinueResponse.java │ │ │ ├── SaslFinalPasswordRequest.java │ │ │ ├── SaslPasswordRequest.java │ │ │ ├── SyncRequest.java │ │ │ └── TlsConnectRequest.java │ │ └── packets │ │ │ ├── AuthenticationRequest.java │ │ │ ├── CommandComplete.java │ │ │ ├── DataRow.java │ │ │ ├── ErrorPacket.java │ │ │ ├── ParameterStatus.java │ │ │ ├── ReadyForQuery.java │ │ │ ├── RowDescription.java │ │ │ ├── parsers │ │ │ ├── BinaryGenerator.java │ │ │ ├── BinaryParser.java │ │ │ └── TextParser.java │ │ │ └── parts │ │ │ ├── ColumnDescription.java │ │ │ ├── ColumnTypes.java │ │ │ ├── ErrorResponseField.java │ │ │ ├── FormatCodeTypes.java │ │ │ └── PgAdbaType.java │ │ ├── execution │ │ ├── DefaultNioLoop.java │ │ ├── NioLoop.java │ │ ├── NioService.java │ │ ├── NioServiceContext.java │ │ └── NioServiceFactory.java │ │ ├── operations │ │ ├── PgArrayRowCountOperation.java │ │ ├── PgCatchOperation.java │ │ ├── PgCloseOperation.java │ │ ├── PgConnectOperation.java │ │ ├── PgLocalOperation.java │ │ ├── PgOperation.java │ │ ├── PgOperationGroup.java │ │ ├── PgOutOperation.java │ │ ├── PgParameterizedRowOperation.java │ │ ├── PgRowCountOperation.java │ │ ├── PgRowOperation.java │ │ ├── PgRowPublisherOperation.java │ │ ├── PgTransactionOperation.java │ │ ├── PgValidationOperation.java │ │ └── helpers │ │ │ ├── ArrayQueryParameter.java │ │ │ ├── FutureArrayQueryParameter.java │ │ │ ├── FutureQueryParameter.java │ │ │ ├── ParameterHolder.java │ │ │ ├── PgTransaction.java │ │ │ ├── QueryParameter.java │ │ │ └── ValueQueryParameter.java │ │ ├── pgdatatypes │ │ ├── Box.java │ │ ├── Circle.java │ │ ├── IntegerRange.java │ │ ├── Line.java │ │ ├── LineSegment.java │ │ ├── LocalDateRange.java │ │ ├── LocalDateTimeRange.java │ │ ├── LongRange.java │ │ ├── NumericRange.java │ │ ├── OffsetDateTimeRange.java │ │ ├── Path.java │ │ ├── Point.java │ │ └── Polygon.java │ │ ├── submissions │ │ ├── ArrayCountSubmission.java │ │ ├── BaseSubmission.java │ │ ├── CloseSubmission.java │ │ ├── ConnectSubmission.java │ │ ├── CountSubmission.java │ │ ├── GroupSubmission.java │ │ ├── LocalSubmission.java │ │ ├── OutSubmission.java │ │ ├── ProcessorSubmission.java │ │ ├── RowSubmission.java │ │ ├── TransactionSubmission.java │ │ └── VoidSubmission.java │ │ └── util │ │ ├── BinaryHelper.java │ │ ├── PgCount.java │ │ ├── PropertyHolder.java │ │ ├── QuadFunction.java │ │ ├── scram │ │ ├── client │ │ │ ├── ScramClient.java │ │ │ └── ScramSession.java │ │ └── common │ │ │ ├── ScramAttributeValue.java │ │ │ ├── ScramAttributes.java │ │ │ ├── ScramFunctions.java │ │ │ ├── ScramMechanism.java │ │ │ ├── ScramMechanisms.java │ │ │ ├── ScramStringFormatting.java │ │ │ ├── exception │ │ │ ├── ScramException.java │ │ │ ├── ScramInvalidServerSignatureException.java │ │ │ ├── ScramParseException.java │ │ │ └── ScramServerErrorException.java │ │ │ ├── gssapi │ │ │ ├── Gs2AttributeValue.java │ │ │ ├── Gs2Attributes.java │ │ │ ├── Gs2CbindFlag.java │ │ │ └── Gs2Header.java │ │ │ ├── message │ │ │ ├── ClientFinalMessage.java │ │ │ ├── ClientFirstMessage.java │ │ │ ├── ServerFinalMessage.java │ │ │ └── ServerFirstMessage.java │ │ │ ├── stringprep │ │ │ ├── StringPreparation.java │ │ │ └── StringPreparations.java │ │ │ └── util │ │ │ ├── AbstractCharAttributeValue.java │ │ │ ├── AbstractStringWritable.java │ │ │ ├── CharAttribute.java │ │ │ ├── CharAttributeValue.java │ │ │ ├── CryptoUtil.java │ │ │ ├── Preconditions.java │ │ │ ├── StringWritable.java │ │ │ ├── StringWritableCsv.java │ │ │ └── UsAsciiUtils.java │ │ └── tlschannel │ │ ├── BufferAllocator.java │ │ ├── ClientTlsChannel.java │ │ ├── HeapBufferAllocator.java │ │ ├── NeedsReadException.java │ │ ├── NeedsTaskException.java │ │ ├── NeedsWriteException.java │ │ ├── TlsChannel.java │ │ ├── TlsChannelBuilder.java │ │ ├── TlsChannelFlowControlException.java │ │ ├── TrackingAllocator.java │ │ ├── WouldBlockException.java │ │ ├── async │ │ ├── AsynchronousTlsChannel.java │ │ ├── AsynchronousTlsChannelGroup.java │ │ └── ExtendedAsynchronousByteChannel.java │ │ ├── impl │ │ ├── BufferHolder.java │ │ ├── ByteBufferSet.java │ │ ├── ByteBufferUtil.java │ │ └── TlsChannelImpl.java │ │ └── util │ │ ├── TlsChannelCallbackException.java │ │ └── Util.java └── resources │ └── META-INF │ └── services │ └── jdk.incubator.sql2.DataSourceFactory └── test ├── java └── org │ └── postgresql │ └── adba │ ├── ArrayCountOperationTest.java │ ├── BackPressureTest.java │ ├── BindParameterTypesTest.java │ ├── CountOperationTest.java │ ├── ErrorStatesTest.java │ ├── FirstLight.java │ ├── InsertSelectDataTypesTest.java │ ├── LoggingTest.java │ ├── PgDataSourceBuilderTest.java │ ├── PgDataSourceTest.java │ ├── PgOperationGroupTest.java │ ├── PgSessionTest.java │ ├── PgSessionTlsTest.java │ ├── ResultTest.java │ ├── SelectDataTypesTest.java │ ├── SelectUnknownDataTypeTest.java │ ├── TransactionTest.java │ ├── communication │ ├── BeFrameParserTest.java │ └── packets │ │ ├── RowDescriptionTest.java │ │ └── parsers │ │ └── TextParserTest.java │ ├── execution │ └── NioLoopTest.java │ ├── pgdatatypes │ ├── BoxTest.java │ ├── CircleTest.java │ ├── DiscreteRangeTest.java │ ├── LineSegmentTest.java │ ├── LineTest.java │ ├── PathTest.java │ ├── PointTest.java │ └── PolygonTest.java │ ├── testutil │ ├── CollectorUtils.java │ ├── ConnectUtil.java │ ├── DatabaseHolder.java │ ├── FutureUtil.java │ └── SimpleRowSubscriber.java │ └── util │ ├── PreparedStatementCacheTest.java │ └── TestLogHandler.java └── resources ├── debian-buster-postgresql11-tls ├── Dockerfile ├── docker-entrypoint.sh ├── generate_cert.sh ├── localhost.crt ├── localhost.csr ├── localhost.key ├── rootCA.crt ├── rootCA.key └── rootCA.srl ├── debian-stretch-postgresql10 ├── Dockerfile ├── docker-entrypoint.sh ├── generate_cert.sh ├── localhost.crt ├── localhost.csr ├── localhost.key ├── rootCA.crt ├── rootCA.key └── rootCA.srl └── keystore.jks /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle/ 2 | .idea/ 3 | *.iml 4 | *~ 5 | .attach_pid* 6 | build/ 7 | gradle/ 8 | gradlew 9 | gradlew.bat 10 | out/ 11 | /.classpath 12 | /.project 13 | /.settings/ 14 | /bin/ 15 | target/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 1997, PostgreSQL Global Development Group 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 17 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 23 | POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /src/main/java/jdk/incubator/sql2/DataSourceFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | package jdk.incubator.sql2; 26 | 27 | import java.util.ServiceLoader; 28 | import java.util.ServiceLoader.Provider; 29 | 30 | /** 31 | * This interface supports injecting a {@link DataSourceFactory}. The SPI 32 | * mechanism will find {@link DataSourceFactory} implementations with the 33 | * given class name. 34 | * 35 | * Implementations must be thread safe. 36 | * 37 | */ 38 | public interface DataSourceFactory { 39 | 40 | /** 41 | * Uses SPI to find a {@link DataSourceFactory} with the requested name or 42 | * {@code null} if one is not found. 43 | * 44 | 45 | * @param name the name of the class that implements the factory 46 | * @return a {@link DataSourceFactory} for {@code name} or {@code null} if one 47 | * is not found 48 | */ 49 | public static DataSourceFactory newFactory(String name) { 50 | if (name == null) throw new IllegalArgumentException("DataSourceFactory name is null"); 51 | return ServiceLoader 52 | .load(DataSourceFactory.class) 53 | .stream() 54 | .filter(p -> p.type().getName().equals(name)) 55 | .findFirst() 56 | .map(Provider::get) 57 | .orElse(null); 58 | } 59 | 60 | /** 61 | * Returns a new {@link DataSource} builder. 62 | * 63 | * @return a {@link DataSource} builder. Not {@code null}. 64 | */ 65 | public DataSource.Builder builder(); 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/jdk/incubator/sql2/PrimitiveOperation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | package jdk.incubator.sql2; 26 | 27 | /** 28 | * A PrimitiveOperation can be submitted, nothing more. Used only by 29 | * {@link OperationGroup#catchOperation} and as a supertype to {@link Operation}. 30 | * 31 | * References in JavaDoc to the "collection of Operations" and "member 32 | * Operations" should be understood to include PrimitiveOperations. The 33 | * distinction between {@link Operation} and {@code PrimitiveOperation} in the 34 | * API is strictly followed as it enables the compiler to catch a significant 35 | * class of errors. The two types are not distinguished in the JavaDoc as making 36 | * such a distinction would not add clarity. 37 | * 38 | * @see Operation 39 | * @see OperationGroup#catchOperation 40 | */ 41 | public interface PrimitiveOperation { 42 | 43 | /** 44 | * Add this {@code PrimitiveOperation} to the tail of the {@link Operation} 45 | * collection of the {@link Session} that created this 46 | * {@code PrimitiveOperation}. A {@code PrimitiveOperation} can be submitted 47 | * only once. Once a {@code PrimitiveOperation} is submitted it is immutable. 48 | * Any attempt to modify a submitted {@code PrimitiveOperation} will throw 49 | * {@link IllegalStateException}. 50 | * 51 | * @return a {@link Submission} for this {@code PrimitiveOperation} 52 | * @throws IllegalStateException if this method is called more than once on 53 | * this {@code PrimitiveOperation} 54 | */ 55 | Submission submit(); 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/jdk/incubator/sql2/RowCountOperation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | package jdk.incubator.sql2; 26 | 27 | import java.time.Duration; 28 | import java.util.function.Consumer; 29 | import java.util.function.Function; 30 | 31 | /** 32 | * An {@link Operation} that returns a count. 33 | * 34 | * @param the type of the result of the {@link Operation} 35 | * @see ParameterizedRowCountOperation 36 | */ 37 | public interface RowCountOperation extends Operation { 38 | 39 | /** 40 | * Sets the result processor for this {@link Operation}. 41 | * 42 | * @param function processes the count produced by executing this 43 | * {@link Operation} and returns the result 44 | * @return this {@code RowCountOperation} 45 | * @throws IllegalStateException if this method has been called previously 46 | */ 47 | public RowCountOperation apply(Function function); 48 | 49 | /** 50 | * {@inheritDoc} 51 | * 52 | * @return this {@code RowCountOperation} 53 | */ 54 | @Override 55 | public RowCountOperation onError(Consumer handler); 56 | 57 | /** 58 | * {@inheritDoc} 59 | * 60 | * @return this {@code RowCountOperation} 61 | */ 62 | @Override 63 | public RowCountOperation timeout(Duration minTime); 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/jdk/incubator/sql2/RowPublisherOperation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | package jdk.incubator.sql2; 26 | 27 | import java.time.Duration; 28 | import java.util.concurrent.CompletionStage; 29 | import java.util.concurrent.Flow; 30 | import java.util.function.Consumer; 31 | 32 | public interface RowPublisherOperation extends Operation { 33 | 34 | /** 35 | * Subscribe to the stream of rows returned by this {@link Operation}. The 36 | * value of the {@code result} parameter is the result of this {@link Operation}. 37 | * 38 | * @param subscriber Not null. 39 | * @param result Not null. 40 | * @return this RowPublisherOperation 41 | */ 42 | public RowPublisherOperation subscribe(Flow.Subscriber subscriber, 43 | CompletionStage result); 44 | // Covariant overrides 45 | 46 | /** 47 | * {@inheritDoc} 48 | * 49 | * @return this {@code RowPublisherOperation} 50 | */ 51 | @Override 52 | public RowPublisherOperation onError(Consumer handler); 53 | 54 | /** 55 | * {@inheritDoc} 56 | * 57 | * @return this {@code RowPublisherOperation} 58 | */ 59 | @Override 60 | public RowPublisherOperation timeout(Duration minTime); 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/jdk/incubator/sql2/SqlArray.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | package jdk.incubator.sql2; 26 | 27 | import java.lang.annotation.Target; 28 | import static java.lang.annotation.ElementType.TYPE; 29 | import java.lang.annotation.Retention; 30 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 31 | 32 | /** 33 | * Identifies a type that represents an ARRAY SQL type. 34 | * Any type to which this annotation is applied must either extend or implement 35 | * java.util.List. Additionally the type must have at least one of the following: 36 | *
    37 | *
  • a public zero-arg constructor
  • 38 | *
  • a public constructor Constructor(int initialCapacity)
  • 39 | *
  • a public constructor Constructor(<? super List<?>>)
  • 40 | *
  • a public static factory method of(<? super List<?>>)
  • 41 | *
42 | * If more than one of the above is supported it is implementation dependent which 43 | * is used. 44 | * 45 | * 46 | */ 47 | @Target({TYPE}) 48 | @Retention(RUNTIME) 49 | public @interface SqlArray { 50 | public String elementSqlTypeName(); 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/jdk/incubator/sql2/SqlParameter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | 26 | package jdk.incubator.sql2; 27 | 28 | import java.lang.annotation.Target; 29 | import static java.lang.annotation.ElementType.METHOD; 30 | import java.lang.annotation.Retention; 31 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 32 | 33 | 34 | /** 35 | * Identifies a method the result of which will be bound to a parameter in a SQL 36 | * statement when an instance of the containing type is passed to 37 | * {@link ParameterizedOperation#set}. 38 | * 39 | * The following pseudo-code describes how an instance is used to set parameter 40 | * values: 41 | * 42 | * {@code 43 | *
    for (Method getter : annotatedMethods) {
44 |  *       Annotation parameter = getter.getAnnotation(SqlParameter.class);
45 |  *       op.set(prefix + parameter.marker(), method.invoke(instance), parameter.sqlType());
46 |  *   }
} 47 | * 48 | */ 49 | @Retention(RUNTIME) 50 | @Target({METHOD}) 51 | public @interface SqlParameter { 52 | 53 | /** 54 | * The marker for SQL parameter that the result of this method will be bound to. 55 | * 56 | * @return the name that identifies the parameter in the SQL 57 | */ 58 | public String marker(); 59 | 60 | /** 61 | * The SQL type of the value bound to the parameter. 62 | * Must be either the name of an enum in {@link SqlType} or the fully 63 | * qualified name of a constant {@link SqlType}, 64 | * for example an enum that implements that interface. 65 | * 66 | * @return the name of the SQL type of the value bound to the parameter 67 | */ 68 | public String sqlType() default ""; 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/jdk/incubator/sql2/SqlSkippedException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | package jdk.incubator.sql2; 26 | 27 | /** 28 | * A {@link SqlException} that is used to complete an {@link Operation} when 29 | * that {@link Operation} is skipped. If an {@link Operation} is skipped the 30 | * {@link Operation} is removed from the head of the queue, no work is sent to 31 | * the database and the {@link java.util.concurrent.CompletionStage} of that 32 | * {@link Operation} is completed exceptionally with a 33 | * {@code SqlSkippedException}. The cause of the {@code SqlSkippedException} is 34 | * the {@link Throwable} that caused the {@link Operation} to be skipped, if 35 | * any. 36 | * 37 | */ 38 | public class SqlSkippedException extends SqlException { 39 | 40 | private static final long serialVersionUID = 1L; 41 | 42 | /** 43 | * 44 | * @param message 45 | * @param cause 46 | * @param sqlState 47 | * @param vendorCode 48 | * @param sql 49 | * @param position 50 | */ 51 | public SqlSkippedException(String message, Throwable cause, String sqlState, int vendorCode, String sql, int position) { 52 | super(message, cause, sqlState, vendorCode, sql, position); 53 | } 54 | 55 | /** 56 | * 57 | * @param cause 58 | */ 59 | public SqlSkippedException(SqlException cause) { 60 | super(cause.getMessage(), cause, cause.getSqlState(), cause.getVendorCode(), cause.getSqlString(), cause.getPosition()); 61 | } 62 | 63 | /** 64 | * 65 | * @param cause 66 | */ 67 | public SqlSkippedException(Throwable cause) { 68 | super(cause.getMessage(), cause, null, -1, null, -1); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/jdk/incubator/sql2/SqlType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | 26 | package jdk.incubator.sql2; 27 | 28 | /** 29 | * Identifies a SQL type. Can be a type defined by standard SQL or a vendor 30 | * specific type. 31 | * 32 | * @see AdbaType 33 | */ 34 | public interface SqlType { 35 | 36 | /** 37 | * 38 | * @return 39 | */ 40 | public String getName(); 41 | 42 | /** 43 | * 44 | * @return 45 | */ 46 | public String getVendor(); 47 | 48 | /** 49 | * 50 | * @return a Java type that best represents values of this SQL type 51 | */ 52 | public Class getJavaType(); 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/jdk/incubator/sql2/TransactionOutcome.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | 26 | package jdk.incubator.sql2; 27 | 28 | /** 29 | * Possible outcomes for a database transaction. 30 | */ 31 | public enum TransactionOutcome { 32 | /** 33 | * The outcome of the transaction is unknown. 34 | */ 35 | UNKNOWN, 36 | 37 | /** 38 | * The outcome of the transaction is in doubt. 39 | */ 40 | IN_DOUBT, 41 | 42 | /** 43 | * The transaction committed successfully. 44 | */ 45 | COMMIT, 46 | 47 | /** 48 | * The transaction rolled back successfully. 49 | */ 50 | ROLLBACK; 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | import org.postgresql.adba.PgDataSourceFactory; 2 | 3 | module org.postgresql.adba { 4 | requires java.logging; 5 | requires java.security.sasl; 6 | exports org.postgresql.adba; 7 | exports org.postgresql.adba.pgdatatypes; 8 | exports jdk.incubator.sql2; 9 | exports org.postgresql.adba.buffer; 10 | exports org.postgresql.adba.execution; 11 | provides jdk.incubator.sql2.DataSourceFactory with PgDataSourceFactory; 12 | uses jdk.incubator.sql2.DataSourceFactory; 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/PgDataSourceBuilder.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba; 2 | 3 | import java.util.function.LongConsumer; 4 | import jdk.incubator.sql2.DataSource; 5 | import jdk.incubator.sql2.DataSource.Builder; 6 | import jdk.incubator.sql2.DataSourceProperty; 7 | import jdk.incubator.sql2.SessionProperty; 8 | import org.postgresql.adba.util.PropertyHolder; 9 | 10 | public class PgDataSourceBuilder implements DataSource.Builder { 11 | private PropertyHolder properties = new PropertyHolder(); 12 | private boolean buildCalled = false; 13 | 14 | @Override 15 | public Builder property(DataSourceProperty property, Object value) { 16 | properties.property(property, value); 17 | 18 | return this; 19 | } 20 | 21 | @Override 22 | public Builder defaultSessionProperty(SessionProperty property, Object value) { 23 | if (buildCalled) { 24 | throw new IllegalStateException("can't modify properties after build() has been called"); 25 | } 26 | 27 | properties.defaultSessionProperty(property, value); 28 | 29 | return this; 30 | } 31 | 32 | @Override 33 | public Builder sessionProperty(SessionProperty property, Object value) { 34 | if (buildCalled) { 35 | throw new IllegalStateException("can't modify properties after build() has been called"); 36 | } 37 | 38 | properties.sessionProperty(property, value); 39 | 40 | return this; 41 | } 42 | 43 | @Override 44 | public Builder registerSessionProperty(SessionProperty property) { 45 | if (buildCalled) { 46 | throw new IllegalStateException("can't modify properties after build() has been called"); 47 | } 48 | 49 | properties.registerSessionProperty(property); 50 | 51 | return this; 52 | } 53 | 54 | @Override 55 | public Builder requestHook(LongConsumer request) { 56 | return this; 57 | } 58 | 59 | @Override 60 | public DataSource build() { 61 | buildCalled = true; 62 | return new PgDataSource(properties); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/PgDataSourceFactory.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba; 2 | 3 | import jdk.incubator.sql2.DataSource; 4 | import jdk.incubator.sql2.DataSourceFactory; 5 | 6 | public class PgDataSourceFactory implements DataSourceFactory { 7 | @Override 8 | public DataSource.Builder builder() { 9 | return new PgDataSourceBuilder(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/PgDataSourceProperty.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba; 2 | 3 | import jdk.incubator.sql2.DataSourceProperty; 4 | import org.postgresql.adba.buffer.ByteBufferPool; 5 | import org.postgresql.adba.execution.NioLoop; 6 | 7 | public enum PgDataSourceProperty implements DataSourceProperty { 8 | /** 9 | * Allows specifying the {@link NioLoop}. 10 | */ 11 | NIO_LOOP(NioLoop.class, null, false), 12 | 13 | /** 14 | * Allows specifying the {@link ByteBufferPool}. 15 | */ 16 | BYTE_BUFFER_POOL(ByteBufferPool.class, null, false); 17 | 18 | private Class range; 19 | private Object defaultValue; 20 | private boolean sensitive; 21 | 22 | PgDataSourceProperty(Class range, Object defaultValue, boolean sensitive) { 23 | this.range = range; 24 | this.defaultValue = defaultValue; 25 | this.sensitive = sensitive; 26 | } 27 | 28 | @Override 29 | public Class range() { 30 | return range; 31 | } 32 | 33 | @Override 34 | public Object defaultValue() { 35 | return defaultValue; 36 | } 37 | 38 | @Override 39 | public boolean isSensitive() { 40 | return sensitive; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/PgSessionDbProperty.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba; 2 | 3 | import java.nio.charset.Charset; 4 | import java.nio.charset.StandardCharsets; 5 | import jdk.incubator.sql2.SessionProperty; 6 | 7 | /** 8 | * Properties on the session that is set by the server. 9 | */ 10 | public enum PgSessionDbProperty implements SessionProperty { 11 | /** 12 | * the charset that the server sets. 13 | */ 14 | CLIENT_ENCODING(Charset.class, StandardCharsets.UTF_8, false), 15 | 16 | /** 17 | * the charset that the server uses. 18 | */ 19 | SERVER_ENCODING(Charset.class, StandardCharsets.UTF_8, false), 20 | 21 | /** 22 | * Style of dates set by the server. 23 | */ 24 | DATESTYLE(String.class, "", false), 25 | 26 | /** 27 | * If the server uses integer of floating point dates. 28 | */ 29 | INTEGER_DATETIMES(String.class, "", false), 30 | 31 | /** 32 | * The format that intervals is sent in. 33 | */ 34 | INTERVALSTYLE(String.class, "", false), 35 | 36 | /** 37 | * If we are connected as super user. 38 | */ 39 | IS_SUPERUSER(String.class, "", false), 40 | 41 | /** 42 | * The server version we are connected to. 43 | */ 44 | SERVER_VERSION(String.class, "", false), 45 | 46 | /** 47 | * The authorization method. 48 | */ 49 | SESSION_AUTHORIZATION(String.class, "", false), 50 | 51 | /** 52 | * If strings are standard conforming. 53 | */ 54 | STANDARD_CONFORMING_STRINGS(String.class, "", false), 55 | 56 | /** 57 | * The time zone of the server we connect to. 58 | */ 59 | TIMEZONE(String.class, "", false); 60 | 61 | 62 | private Class range; 63 | private Object defaultValue; 64 | private boolean sensitive; 65 | 66 | PgSessionDbProperty(Class range, Object defaultValue, boolean sensitive) { 67 | this.range = range; 68 | this.defaultValue = defaultValue; 69 | this.sensitive = sensitive; 70 | } 71 | 72 | @Override 73 | public Class range() { 74 | return range; 75 | } 76 | 77 | @Override 78 | public Object defaultValue() { 79 | return defaultValue; 80 | } 81 | 82 | @Override 83 | public boolean isSensitive() { 84 | return sensitive; 85 | } 86 | 87 | /** 88 | * Returns the connection property that matches the supplied string. 89 | * 90 | * @param name name to search for 91 | * @return the matching property 92 | */ 93 | public static PgSessionDbProperty lookup(String name) { 94 | for (PgSessionDbProperty prop : values()) { 95 | if (prop.toString().equalsIgnoreCase(name)) { 96 | return prop; 97 | } 98 | } 99 | 100 | throw new IllegalArgumentException("no property with name: " + name); 101 | } 102 | 103 | } 104 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/PgSubmission.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba; 2 | 3 | import jdk.incubator.sql2.Submission; 4 | import org.postgresql.adba.communication.packets.DataRow; 5 | import org.postgresql.adba.operations.helpers.ParameterHolder; 6 | 7 | import java.util.List; 8 | import java.util.concurrent.ExecutionException; 9 | import java.util.concurrent.atomic.AtomicBoolean; 10 | import java.util.function.Consumer; 11 | import java.util.stream.Collector; 12 | 13 | public interface PgSubmission extends Submission { 14 | enum Types { 15 | COUNT, 16 | ROW, 17 | CLOSE, 18 | CONNECT, 19 | TRANSACTION, 20 | ARRAY_COUNT, 21 | VOID, 22 | PROCESSOR, 23 | OUT_PARAMETER, 24 | LOCAL, 25 | GROUP, 26 | CATCH; 27 | } 28 | 29 | String getSql(); 30 | 31 | AtomicBoolean getSendConsumed(); 32 | 33 | ParameterHolder getHolder(); 34 | 35 | Types getCompletionType(); 36 | 37 | void setCollector(Collector collector); 38 | 39 | Object finish(Object finishObject); 40 | 41 | void addRow(DataRow row); 42 | 43 | List getParamTypes() throws ExecutionException, InterruptedException; 44 | 45 | int numberOfQueryRepetitions() throws ExecutionException, InterruptedException; 46 | 47 | Consumer getErrorHandler(); 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/buffer/ByteBufferPool.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.buffer; 2 | 3 | /** 4 | * Pool of {@link PooledByteBuffer} instances. 5 | * 6 | * @author Daniel Sagenschneider 7 | */ 8 | public interface ByteBufferPool { 9 | 10 | /** 11 | * Obtains the {@link PooledByteBuffer}. 12 | * 13 | * @return {@link PooledByteBuffer}. 14 | */ 15 | PooledByteBuffer getPooledByteBuffer(); 16 | 17 | } -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/buffer/DefaultByteBufferPool.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.buffer; 2 | 3 | import java.nio.ByteBuffer; 4 | import java.util.Queue; 5 | import java.util.concurrent.ConcurrentLinkedQueue; 6 | 7 | /** 8 | * Default {@link ByteBufferPool}. 9 | * 10 | * @author Daniel Sagenschneider 11 | */ 12 | public class DefaultByteBufferPool implements ByteBufferPool { 13 | 14 | /** 15 | * Pool of {@link PooledByteBuffer} instances. 16 | */ 17 | private final Queue pool = new ConcurrentLinkedQueue<>(); 18 | 19 | /** 20 | * Size of buffers. 21 | */ 22 | private final int bufferSize; 23 | 24 | /** 25 | * Instantiate. 26 | */ 27 | public DefaultByteBufferPool() { 28 | // TODO consider specifying buffer size from properties 29 | this.bufferSize = 8192; // largest 2 based size fitting jumbo ethernet packet 30 | } 31 | 32 | /* 33 | * ================= ByteBufferPool ====================== 34 | */ 35 | 36 | @Override 37 | public PooledByteBuffer getPooledByteBuffer() { 38 | 39 | // Obtain the next pooled buffer 40 | PooledByteBuffer buffer = pool.poll(); 41 | if (buffer != null) { 42 | return buffer; 43 | } 44 | 45 | // No pooled, so create buffer 46 | // TODO consider blocking thread if too many active buffers to keep memory down 47 | return new PooledByteBufferImpl(); 48 | } 49 | 50 | private class PooledByteBufferImpl implements PooledByteBuffer { 51 | 52 | private final ByteBuffer buffer = ByteBuffer.allocateDirect(bufferSize); 53 | 54 | /* 55 | * =============== PooledByteBuffer ==================== 56 | */ 57 | 58 | @Override 59 | public ByteBuffer getByteBuffer() { 60 | return this.buffer; 61 | } 62 | 63 | @Override 64 | public void release() { 65 | pool.add(this); 66 | } 67 | } 68 | 69 | } -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/buffer/PooledByteBuffer.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.buffer; 2 | 3 | import java.nio.ByteBuffer; 4 | 5 | /** 6 | * Pooled {@link ByteBuffer}. 7 | * 8 | * @author Daniel Sagenschneider 9 | */ 10 | public interface PooledByteBuffer { 11 | 12 | /** 13 | * Obtains the {@link ByteBuffer}. 14 | * 15 | * @return {@link ByteBuffer}. 16 | */ 17 | ByteBuffer getByteBuffer(); 18 | 19 | /** 20 | * Releases this back to the pool. 21 | */ 22 | void release(); 23 | 24 | } -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/communication/BeFrame.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.communication; 2 | 3 | public class BeFrame { 4 | public enum BackendTag { 5 | AUTHENTICATION('R'), 6 | CANCELLATION_KEY_DATA('K'), 7 | BIND_COMPLETE('2'), 8 | CLOSE_COMPLETE('3'), 9 | COMMAND_COMPLETE('C'), 10 | COPY_DATA('d'), 11 | COPY_DONE('c'), 12 | COPY_IN_RESPONSE('G'), 13 | COPY_OUT_RESPONSE('H'), 14 | COPY_BOTH_RESPONSE('W'), 15 | DATA_ROW('D'), 16 | EMPTY_QUERY_RESPONSE('I'), 17 | ERROR_RESPONSE('E'), 18 | FUNCTION_CALL_RESPONSE('V'), 19 | NEGOTIATE_PROTOCOL_VERSION('v'), 20 | NO_DATA('n'), 21 | NOTICE_RESPONSE('N'), 22 | NOTIFICATION_RESPONSE('A'), 23 | PARAM_DESCRIPTION('t'), 24 | PARAM_STATUS('S'), 25 | PARSE_COMPLETE('1'), 26 | PORTAL_SUSPENDED('s'), 27 | READY_FOR_QUERY('Z'), 28 | ROW_DESCRIPTION('T'), 29 | TLS_HANDSHAKE('/'); 30 | 31 | private char tag; 32 | 33 | BackendTag(char tag) { 34 | this.tag = tag; 35 | } 36 | 37 | /** 38 | * Find the BackendTag that corresponds to the supplied byte value. 39 | * @param input byte to search for 40 | * @return the corresponding BackendTag 41 | */ 42 | public static BackendTag lookup(byte input) { 43 | for (BackendTag bt : values()) { 44 | if (input == bt.tag) { 45 | return bt; 46 | } 47 | } 48 | throw new IllegalArgumentException("There is no backend server tag that matches byte " + input); 49 | } 50 | } 51 | 52 | private BackendTag tag; 53 | private byte[] payload; 54 | 55 | public BeFrame(byte tag, byte[] payload) { 56 | this.tag = BackendTag.lookup(tag); 57 | this.payload = payload; 58 | } 59 | 60 | public BackendTag getTag() { 61 | return tag; 62 | } 63 | 64 | // TODO make this InputStream from PooledByteBuffer instances (avoids unnecessary copies) 65 | public byte[] getPayload() { 66 | return payload; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/communication/FrontendTag.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.communication; 2 | 3 | public enum FrontendTag { 4 | BIND('B'), 5 | DESCRIBE('D'), 6 | EXECUTE('E'), 7 | PARSE('P'), 8 | PASSWORD_MESSAGE('p'), 9 | QUERY('Q'), 10 | SASL_INITIAL_RESPONSE('p'), 11 | SASL_RESPONSE('p'), 12 | SYNC('S'), 13 | TERMINATE('X'); 14 | 15 | private char tag; 16 | 17 | FrontendTag(char tag) { 18 | this.tag = tag; 19 | } 20 | 21 | /** 22 | * Search for the correct FrontendTag based on byte value. 23 | * @param input the byte to search for 24 | * @return the corresponding FrontendTag 25 | */ 26 | public static FrontendTag lookup(byte input) { 27 | for (FrontendTag bt : values()) { 28 | if (input == bt.tag) { 29 | return bt; 30 | } 31 | } 32 | throw new IllegalArgumentException("There is no backend server tag that matches byte " + input); 33 | } 34 | 35 | public byte getByte() { 36 | return (byte)tag; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/communication/NetworkConnect.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.communication; 2 | 3 | import java.io.IOException; 4 | 5 | /** 6 | * Connect to the PostgreSql. 7 | * 8 | * @author Daniel Sagenschneider 9 | */ 10 | public interface NetworkConnect extends NetworkErrorHandler { 11 | 12 | /** 13 | * Triggers the connect. 14 | * 15 | * @param context {@link NetworkConnectContext}. 16 | * @throws IOException If failure to initialise. 17 | */ 18 | void connect(NetworkConnectContext context) throws IOException; 19 | 20 | /** 21 | * Handles the connect by the {@link NetworkRequest}. 22 | * 23 | * @param context {@link NetworkConnectContext}. 24 | * @return Possible {@link NetworkRequest} to undertake immediately after 25 | * connection established. 26 | * @throws IOException If failure in handling the connect. 27 | */ 28 | NetworkRequest finishConnect(NetworkConnectContext context) throws IOException; 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/communication/NetworkConnectContext.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.communication; 2 | 3 | /** 4 | * Context for the connecting the {@link NetworkRequest}. 5 | * 6 | * @author Daniel Sagenschneider 7 | */ 8 | public interface NetworkConnectContext extends NetworkContext { 9 | } -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/communication/NetworkContext.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.communication; 2 | 3 | import java.nio.channels.SocketChannel; 4 | import jdk.incubator.sql2.SessionProperty; 5 | import org.postgresql.adba.util.PropertyHolder; 6 | 7 | /** 8 | * Context available to all {@link NetworkRequest} events. 9 | * 10 | * @author Daniel Sagenschneider 11 | */ 12 | public interface NetworkContext { 13 | 14 | /** 15 | * Obtains the {@link SocketChannel}. 16 | * 17 | * @return {@link SocketChannel}. 18 | */ 19 | SocketChannel getSocketChannel(); 20 | 21 | /** 22 | * Obtains the {@link SessionProperty} values. 23 | * 24 | * @return {@link SessionProperty} values. 25 | */ 26 | PropertyHolder getProperties(); 27 | 28 | void startTls(); 29 | } -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/communication/NetworkErrorHandler.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.communication; 2 | 3 | /** 4 | * Interaction with the network. 5 | * 6 | * @author Daniel Sagenschneider 7 | */ 8 | public interface NetworkErrorHandler { 9 | 10 | /** 11 | * Handles the failure. 12 | * 13 | * @param ex Failure. 14 | * @return Optional {@link NetworkResponse}. May be null. 15 | */ 16 | NetworkResponse handleException(Throwable ex); 17 | 18 | } -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/communication/NetworkOutputStream.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.communication; 2 | 3 | import java.io.IOException; 4 | import java.io.OutputStream; 5 | 6 | /** 7 | * {@link OutputStream} to the {@link NetworkConnection}. 8 | * 9 | * @author Daniel Sagenschneider 10 | */ 11 | public abstract class NetworkOutputStream extends OutputStream { 12 | 13 | /** 14 | * Initialises the packet. 15 | * 16 | * @throws IOException If fails to initialise the packet. 17 | */ 18 | public abstract void initPacket() throws IOException; 19 | 20 | /** 21 | * Writes text into the packet. 22 | * 23 | * @param text Text. 24 | * @throws IOException If fails to write the text. 25 | */ 26 | public abstract void write(String text) throws IOException; 27 | 28 | /** 29 | * Writes the terminator. 30 | * 31 | * @throws IOException If fails to write the terminator. 32 | */ 33 | public void writeTerminator() throws IOException { 34 | this.write(0); 35 | } 36 | 37 | /** 38 | * Completes the packet. 39 | * 40 | * @throws IOException If fails to complete the packet. 41 | */ 42 | public abstract void completePacket() throws IOException; 43 | 44 | } -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/communication/NetworkReadContext.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.communication; 2 | 3 | import org.postgresql.adba.PgSessionDbProperty; 4 | 5 | /** 6 | * Context for writing to the network. 7 | * 8 | * @author Daniel Sagenschneider 9 | */ 10 | public interface NetworkReadContext extends NetworkContext { 11 | 12 | /** 13 | * Obtains the {@link BeFrame} just read. 14 | * 15 | * @return {@link BeFrame} just read. 16 | */ 17 | BeFrame getBeFrame(); 18 | 19 | /** 20 | * Obtains the {@link PreparedStatementCache}. 21 | * 22 | * @return {@link PreparedStatementCache}. 23 | */ 24 | PreparedStatementCache getPreparedStatementCache(); 25 | 26 | /** 27 | * set a {@link PgSessionDbProperty} that came from the server. 28 | * 29 | * @param property {@link PgSessionDbProperty}. 30 | * @param value Value. 31 | */ 32 | void setProperty(PgSessionDbProperty property, Object value); 33 | 34 | /** 35 | * Triggers for a {@link NetworkRequest} to be undertaken. 36 | * 37 | * @param request {@link NetworkRequest} to be undertaken. 38 | */ 39 | void write(NetworkRequest request); 40 | 41 | /** 42 | * Triggers for a write. 43 | */ 44 | void writeRequired(); 45 | 46 | } -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/communication/NetworkRequest.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.communication; 2 | 3 | /** 4 | * Action over the network to the PostgreSql database. 5 | * 6 | * @author Daniel Sagenschneider 7 | */ 8 | public interface NetworkRequest { 9 | 10 | /** 11 | * Writes this {@link NetworkRequest} to the network. 12 | * 13 | * @param context {@link NetworkWriteContext}. 14 | * @return Optional further {@link NetworkRequest} to be undertaken. May be 15 | * null if no further {@link NetworkRequest}. 16 | * @throws Exception If failure in writing to the network. 17 | */ 18 | NetworkRequest write(NetworkWriteContext context) throws Exception; 19 | 20 | /** 21 | * Indicates the {@link NetworkRequest} is blocking further 22 | * {@link NetworkRequest} instances from being sent over the network. 23 | * 24 | * @return true to block further {@link NetworkRequest} instances 25 | * from being sent. 26 | */ 27 | default boolean isBlocking() { 28 | return false; 29 | } 30 | 31 | /** 32 | * Obtains the {@link NetworkResponse} for a required response. 33 | * 34 | * @return {@link NetworkResponse} for required response. null if 35 | * no response. 36 | */ 37 | default NetworkResponse getRequiredResponse() { 38 | return null; 39 | } 40 | 41 | } -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/communication/NetworkResponse.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.communication; 2 | 3 | import java.io.IOException; 4 | 5 | /** 6 | * Handler for response from network. 7 | * 8 | * @author Daniel Sagenschneider 9 | */ 10 | public interface NetworkResponse extends NetworkErrorHandler { 11 | 12 | /** 13 | * Handles the read by the {@link NetworkRequest}. 14 | * 15 | * @param context {@link NetworkReadContext}. 16 | * @return Optional further {@link NetworkResponse} to be received. 17 | * @throws IOException If failure in handling the read. 18 | */ 19 | NetworkResponse read(NetworkReadContext context) throws IOException; 20 | } -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/communication/NetworkWriteContext.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.communication; 2 | 3 | /** 4 | * Context for writing to the network. 5 | * 6 | * @author Daniel Sagenschneider 7 | */ 8 | public interface NetworkWriteContext extends NetworkContext { 9 | 10 | /** 11 | * Obtains the {@link NetworkOutputStream} to write content to the network. 12 | * 13 | * @return {@link NetworkOutputStream} to write content to the network. 14 | */ 15 | NetworkOutputStream getOutputStream(); 16 | 17 | /** 18 | * Obtains the {@link PreparedStatementCache}. 19 | * 20 | * @return {@link PreparedStatementCache}. 21 | */ 22 | PreparedStatementCache getPreparedStatementCache(); 23 | 24 | } -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/communication/PreparedStatementCache.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.communication; 2 | 3 | import java.util.HashMap; 4 | import java.util.List; 5 | import java.util.Map; 6 | import java.util.Objects; 7 | 8 | import org.postgresql.adba.communication.network.Query; 9 | 10 | public class PreparedStatementCache { 11 | 12 | /** 13 | * As only used on networking thread, is thread safe. 14 | */ 15 | private Map sqlToQuery = new HashMap<>(); 16 | 17 | /** 18 | * Obtains the {@link Query} for the SQL. 19 | * 20 | * @param sql SQL. 21 | * @param params Parameters. 22 | * @return {@link Query}. 23 | */ 24 | public Query getQuery(String sql, List params) { 25 | if (sql == null) { 26 | throw new IllegalArgumentException("No SQL provided"); 27 | } 28 | 29 | // Obtain or create the query 30 | return sqlToQuery.computeIfAbsent(new StatementKey(sql, params), key -> new Query()); 31 | } 32 | 33 | private class StatementKey { 34 | private final String sql; 35 | private final List params; 36 | 37 | private StatementKey(String sql, List params) { 38 | this.sql = sql; 39 | this.params = params; 40 | } 41 | 42 | @Override 43 | public boolean equals(Object o) { 44 | if (this == o) { 45 | return true; 46 | } 47 | 48 | if (o == null || getClass() != o.getClass()) { 49 | return false; 50 | } 51 | 52 | StatementKey that = (StatementKey) o; 53 | return Objects.equals(sql, that.sql) && Objects.equals(params, that.params); 54 | } 55 | 56 | @Override 57 | public int hashCode() { 58 | return Objects.hash(sql, params); 59 | } 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/communication/TableCell.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.communication; 2 | 3 | import org.postgresql.adba.communication.packets.parts.ColumnDescription; 4 | 5 | public class TableCell { 6 | private byte[] bytes; 7 | private int start; 8 | private int stop; 9 | private ColumnDescription columnDescription; 10 | 11 | /** 12 | * one cell in the returned result set. 13 | * @param bytes the payload 14 | * @param start where in the payload the information starts 15 | * @param stop where in the payload the information stops 16 | * @param columnDescription description of the data type for this cell 17 | */ 18 | public TableCell(byte[] bytes, int start, int stop, ColumnDescription columnDescription) { 19 | this.bytes = bytes; 20 | this.start = start; 21 | this.stop = stop; 22 | this.columnDescription = columnDescription; 23 | } 24 | 25 | public byte[] getBytes() { 26 | return bytes; 27 | } 28 | 29 | public int getStart() { 30 | return start; 31 | } 32 | 33 | public int getStop() { 34 | return stop; 35 | } 36 | 37 | public ColumnDescription getColumnDescription() { 38 | return columnDescription; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/communication/network/AbstractPortalResponse.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.communication.network; 2 | 3 | import org.postgresql.adba.communication.NetworkResponse; 4 | 5 | /** 6 | * Abstract {@link Portal} {@link NetworkResponse}. 7 | * 8 | * @author Daniel Sagenschneider 9 | */ 10 | public abstract class AbstractPortalResponse implements NetworkResponse { 11 | 12 | /** 13 | * {@link Portal}. 14 | */ 15 | protected final Portal portal; 16 | 17 | /** 18 | * Instantiate. 19 | * 20 | * @param portal {@link Portal}. 21 | */ 22 | public AbstractPortalResponse(Portal portal) { 23 | this.portal = portal; 24 | } 25 | 26 | @Override 27 | public NetworkResponse handleException(Throwable ex) { 28 | portal.handleException(ex); 29 | return new ReadyForQueryResponse(); 30 | } 31 | } -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/communication/network/AuthenticationResponse.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.communication.network; 2 | 3 | import java.util.concurrent.CompletableFuture; 4 | import java.util.function.Consumer; 5 | import org.postgresql.adba.PgSessionDbProperty; 6 | import org.postgresql.adba.communication.BeFrame; 7 | import org.postgresql.adba.communication.NetworkReadContext; 8 | import org.postgresql.adba.communication.NetworkResponse; 9 | import org.postgresql.adba.communication.packets.AuthenticationRequest; 10 | import org.postgresql.adba.communication.packets.ParameterStatus; 11 | import org.postgresql.adba.submissions.ConnectSubmission; 12 | 13 | /** 14 | * Authentication success {@link NetworkResponse}. 15 | * 16 | * @author Daniel Sagenschneider 17 | */ 18 | public class AuthenticationResponse implements NetworkResponse { 19 | 20 | private final ConnectSubmission connectSubmission; 21 | 22 | public AuthenticationResponse(ConnectSubmission connectSubmission) { 23 | this.connectSubmission = connectSubmission; 24 | } 25 | 26 | @Override 27 | public NetworkResponse read(NetworkReadContext context) { 28 | // Expecting authentication challenge 29 | BeFrame frame = context.getBeFrame(); 30 | switch (frame.getTag()) { 31 | 32 | case AUTHENTICATION: 33 | AuthenticationRequest authentication = new AuthenticationRequest(frame.getPayload()); 34 | switch (authentication.getType()) { 35 | 36 | case SUCCESS: 37 | // Connected, so trigger any waiting submissions 38 | connectSubmission.finish(null); 39 | return this; 40 | 41 | default: 42 | throw new IllegalStateException("Unhandled authentication " + authentication.getType()); 43 | } 44 | 45 | case PARAM_STATUS: 46 | // Load parameters for connection 47 | ParameterStatus paramStatus = new ParameterStatus(frame.getPayload()); 48 | try { 49 | context.setProperty(PgSessionDbProperty.lookup(paramStatus.getName()), paramStatus.getValue()); 50 | } catch (IllegalArgumentException e) { 51 | //e.printStackTrace(); 52 | } 53 | return this; 54 | 55 | case CANCELLATION_KEY_DATA: 56 | // TODO handle cancellation key 57 | return this; 58 | 59 | case READY_FOR_QUERY: 60 | return null; 61 | 62 | default: 63 | throw new IllegalStateException("Invalid tag '" + frame.getTag() + "' for " + this.getClass().getSimpleName()); 64 | } 65 | } 66 | 67 | @Override 68 | public NetworkResponse handleException(Throwable ex) { 69 | Consumer errorHandler = connectSubmission.getErrorHandler(); 70 | if (errorHandler != null) { 71 | connectSubmission.getErrorHandler().accept(ex); 72 | } 73 | ((CompletableFuture)connectSubmission.getCompletionStage()).completeExceptionally(ex); 74 | return null; 75 | } 76 | 77 | } -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/communication/network/BindRequest.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.communication.network; 2 | 3 | import org.postgresql.adba.communication.FrontendTag; 4 | import org.postgresql.adba.communication.NetworkOutputStream; 5 | import org.postgresql.adba.communication.NetworkRequest; 6 | import org.postgresql.adba.communication.NetworkResponse; 7 | import org.postgresql.adba.communication.NetworkWriteContext; 8 | import org.postgresql.adba.operations.helpers.ParameterHolder; 9 | import org.postgresql.adba.operations.helpers.QueryParameter; 10 | import org.postgresql.adba.util.BinaryHelper; 11 | 12 | /** 13 | * Bind {@link NetworkRequest}. 14 | * 15 | * @author Daniel Sagenschneider 16 | */ 17 | public class BindRequest implements NetworkRequest { 18 | 19 | private final Portal portal; 20 | 21 | public BindRequest(Portal portal) { 22 | this.portal = portal; 23 | } 24 | 25 | /* 26 | * ================= NetworkRequest ========================= 27 | */ 28 | 29 | @Override 30 | public NetworkRequest write(NetworkWriteContext context) throws Exception { 31 | 32 | // Obtain the query details 33 | ParameterHolder holder = portal.getParameterHolder(); 34 | 35 | // Write the packet 36 | NetworkOutputStream wire = context.getOutputStream(); 37 | wire.write(FrontendTag.BIND.getByte()); 38 | wire.initPacket(); 39 | wire.write(portal.getPortalName()); 40 | wire.write(portal.getQuery().getQueryName()); 41 | wire.write(BinaryHelper.writeShort(holder.size())); 42 | for (QueryParameter qp : holder.parameters()) { 43 | wire.write(BinaryHelper.writeShort(qp.getParameterFormatCode())); 44 | } 45 | wire.write(BinaryHelper.writeShort(holder.size())); 46 | int paramIndex = 0; 47 | for (QueryParameter qp : holder.parameters()) { 48 | byte[] paramData = qp.getParameter(paramIndex++); 49 | if (paramData.length == 0) { // handling the null special case 50 | wire.write(BinaryHelper.writeInt(-1)); 51 | } else { 52 | wire.write(BinaryHelper.writeInt(paramData.length)); 53 | wire.write(paramData); 54 | } 55 | } 56 | wire.writeTerminator(); 57 | wire.writeTerminator(); 58 | wire.completePacket(); 59 | 60 | // Next step to execute 61 | return new ExecuteRequest<>(portal); 62 | } 63 | 64 | @Override 65 | public NetworkResponse getRequiredResponse() { 66 | return new BindResponse(portal); 67 | } 68 | 69 | } -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/communication/network/BindResponse.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.communication.network; 2 | 3 | import java.io.IOException; 4 | 5 | import org.postgresql.adba.communication.BeFrame; 6 | import org.postgresql.adba.communication.NetworkReadContext; 7 | import org.postgresql.adba.communication.NetworkResponse; 8 | 9 | /** 10 | * Bind {@link NetworkResponse}. 11 | * 12 | * @author Daniel Sagenschneider 13 | */ 14 | public class BindResponse extends AbstractPortalResponse { 15 | 16 | public BindResponse(Portal portal) { 17 | super(portal); 18 | } 19 | 20 | @Override 21 | public NetworkResponse read(NetworkReadContext context) throws IOException { 22 | BeFrame frame = context.getBeFrame(); 23 | switch (frame.getTag()) { 24 | 25 | case BIND_COMPLETE: 26 | return null; // Nothing further 27 | 28 | default: 29 | throw new IllegalStateException("Invalid tag '" + frame.getTag() + "' for " + this.getClass().getSimpleName()); 30 | } 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/communication/network/CloseRequest.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.communication.network; 2 | 3 | import org.postgresql.adba.communication.FrontendTag; 4 | import org.postgresql.adba.communication.NetworkOutputStream; 5 | import org.postgresql.adba.communication.NetworkRequest; 6 | import org.postgresql.adba.communication.NetworkResponse; 7 | import org.postgresql.adba.communication.NetworkWriteContext; 8 | import org.postgresql.adba.submissions.CloseSubmission; 9 | 10 | /** 11 | * Close {@link NetworkRequest}. 12 | * 13 | * @author Daniel Sagenschneider 14 | */ 15 | public class CloseRequest implements NetworkRequest { 16 | 17 | private final CloseSubmission submission; 18 | 19 | /** 20 | * Instantiate. 21 | * 22 | * @param submission the submission this request connects to 23 | */ 24 | public CloseRequest(CloseSubmission submission) { 25 | this.submission = submission; 26 | } 27 | 28 | @Override 29 | public NetworkRequest write(NetworkWriteContext context) throws Exception { 30 | 31 | // Send the close 32 | NetworkOutputStream wire = context.getOutputStream(); 33 | wire.write(FrontendTag.TERMINATE.getByte()); 34 | wire.initPacket(); 35 | wire.completePacket(); 36 | wire.close(); 37 | 38 | // Nothing further 39 | return null; 40 | } 41 | 42 | @Override 43 | public NetworkResponse getRequiredResponse() { 44 | return new CloseResponse(submission); 45 | } 46 | } -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/communication/network/CloseResponse.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.communication.network; 2 | 3 | import java.io.IOException; 4 | import jdk.incubator.sql2.Submission; 5 | import org.postgresql.adba.communication.NetworkReadContext; 6 | import org.postgresql.adba.communication.NetworkResponse; 7 | 8 | public class CloseResponse implements NetworkResponse { 9 | 10 | private final Submission submission; 11 | 12 | public CloseResponse(Submission submission) { 13 | this.submission = submission; 14 | } 15 | 16 | @Override 17 | public NetworkResponse read(NetworkReadContext context) throws IOException { 18 | submission.getCompletionStage().toCompletableFuture().complete(null); 19 | return null; 20 | } 21 | 22 | @Override 23 | public NetworkResponse handleException(Throwable ex) { 24 | submission.getCompletionStage().toCompletableFuture().completeExceptionally(ex); 25 | return null; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/communication/network/DescribeRequest.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.communication.network; 2 | 3 | import org.postgresql.adba.communication.FrontendTag; 4 | import org.postgresql.adba.communication.NetworkOutputStream; 5 | import org.postgresql.adba.communication.NetworkRequest; 6 | import org.postgresql.adba.communication.NetworkResponse; 7 | import org.postgresql.adba.communication.NetworkWriteContext; 8 | 9 | /** 10 | * Describe {@link NetworkRequest}. 11 | * 12 | * @author Daniel Sagenschneider 13 | */ 14 | public class DescribeRequest implements NetworkRequest { 15 | 16 | private final Portal portal; 17 | 18 | /** 19 | * Instantiate. 20 | * 21 | * @param portal the portal this request connects to 22 | */ 23 | public DescribeRequest(Portal portal) { 24 | this.portal = portal; 25 | } 26 | 27 | /* 28 | * ================= NetworkRequest ========================= 29 | */ 30 | 31 | @Override 32 | public NetworkRequest write(NetworkWriteContext context) throws Exception { 33 | 34 | // Send describe packet 35 | NetworkOutputStream wire = context.getOutputStream(); 36 | wire.write(FrontendTag.DESCRIBE.getByte()); 37 | wire.initPacket(); 38 | wire.write('S'); 39 | wire.write(portal.getQuery().getQueryName()); 40 | wire.completePacket(); 41 | 42 | // Next step to bind 43 | return new BindRequest<>(portal); 44 | } 45 | 46 | @Override 47 | public NetworkResponse getRequiredResponse() { 48 | return new DescribeResponse(portal); 49 | } 50 | 51 | } -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/communication/network/DescribeResponse.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.communication.network; 2 | 3 | import org.postgresql.adba.communication.BeFrame; 4 | import org.postgresql.adba.communication.NetworkReadContext; 5 | import org.postgresql.adba.communication.NetworkResponse; 6 | import org.postgresql.adba.communication.packets.RowDescription; 7 | 8 | import java.io.IOException; 9 | 10 | /** 11 | * Describe {@link NetworkResponse}. 12 | * 13 | * @author Daniel Sagenschneider 14 | */ 15 | public class DescribeResponse extends AbstractPortalResponse { 16 | 17 | public DescribeResponse(Portal portal) { 18 | super(portal); 19 | } 20 | 21 | @Override 22 | public NetworkResponse read(NetworkReadContext context) throws IOException { 23 | BeFrame frame = context.getBeFrame(); 24 | switch (frame.getTag()) { 25 | 26 | case NO_DATA: 27 | return null; 28 | 29 | case PARAM_DESCRIPTION: 30 | return this; // wait on row description 31 | 32 | case ROW_DESCRIPTION: 33 | RowDescription rowDescription = new RowDescription(frame.getPayload()); 34 | portal.getQuery().setRowDescription(rowDescription); 35 | return null; // nothing further 36 | 37 | default: 38 | throw new IllegalStateException("Invalid tag '" + frame.getTag() + "' for " + this.getClass().getSimpleName()); 39 | } 40 | } 41 | 42 | } -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/communication/network/ExecuteRequest.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.communication.network; 2 | 3 | import org.postgresql.adba.communication.FrontendTag; 4 | import org.postgresql.adba.communication.NetworkOutputStream; 5 | import org.postgresql.adba.communication.NetworkRequest; 6 | import org.postgresql.adba.communication.NetworkResponse; 7 | import org.postgresql.adba.communication.NetworkWriteContext; 8 | import org.postgresql.adba.util.BinaryHelper; 9 | 10 | /** 11 | * Execute {@link NetworkRequest}. 12 | * 13 | * @author Daniel Sagenschneider 14 | */ 15 | public class ExecuteRequest implements NetworkRequest { 16 | 17 | private final Portal portal; 18 | 19 | public ExecuteRequest(Portal portal) { 20 | this.portal = portal; 21 | } 22 | 23 | /* 24 | * ================= NetworkRequest ========================= 25 | */ 26 | 27 | @Override 28 | public NetworkRequest write(NetworkWriteContext context) throws Exception { 29 | 30 | // Obtain the query details 31 | NetworkOutputStream wire = context.getOutputStream(); 32 | wire.write(FrontendTag.EXECUTE.getByte()); 33 | wire.initPacket(); 34 | wire.write(portal.getPortalName()); 35 | wire.write(BinaryHelper.writeInt(0)); // number of rows to return, 0 == all 36 | wire.completePacket(); 37 | 38 | // TODO Auto-generated method stub 39 | return new SyncRequest(portal); 40 | } 41 | 42 | @Override 43 | public NetworkResponse getRequiredResponse() { 44 | return new ExecuteResponse(portal); 45 | } 46 | 47 | } -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/communication/network/ExecuteResponse.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.communication.network; 2 | 3 | import java.io.IOException; 4 | 5 | import org.postgresql.adba.communication.BeFrame; 6 | import org.postgresql.adba.communication.NetworkReadContext; 7 | import org.postgresql.adba.communication.NetworkResponse; 8 | import org.postgresql.adba.communication.packets.CommandComplete; 9 | import org.postgresql.adba.communication.packets.DataRow; 10 | 11 | /** 12 | * Execute {@link NetworkResponse}. 13 | * 14 | * @author Daniel Sagenschneider 15 | */ 16 | public class ExecuteResponse extends AbstractPortalResponse { 17 | 18 | public ExecuteResponse(Portal portal) { 19 | super(portal); 20 | } 21 | 22 | @Override 23 | public NetworkResponse read(NetworkReadContext context) throws IOException { 24 | BeFrame frame = context.getBeFrame(); 25 | switch (frame.getTag()) { 26 | 27 | case DATA_ROW: 28 | if (!portal.getQuery().isCanceled()) { 29 | DataRow dataRow = new DataRow(frame.getPayload(), portal.getQuery().getRowDescription().getDescriptions(), 30 | portal.nextRowNumber(), portal.getQuery()); 31 | portal.addDataRow(dataRow); 32 | } 33 | return this; 34 | 35 | case COMMAND_COMPLETE: 36 | CommandComplete complete = new CommandComplete(frame.getPayload()); 37 | portal.commandComplete(complete, context.getSocketChannel()); 38 | return this; 39 | 40 | case READY_FOR_QUERY: 41 | return null; 42 | 43 | default: 44 | throw new IllegalStateException("Invalid tag '" + frame.getTag() + "' for " + getClass().getSimpleName()); 45 | } 46 | } 47 | 48 | } -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/communication/network/ImmediateComplete.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.communication.network; 2 | 3 | import org.postgresql.adba.PgSubmission; 4 | import org.postgresql.adba.communication.NetworkRequest; 5 | import org.postgresql.adba.communication.NetworkWriteContext; 6 | 7 | /** 8 | * Immediate completes the {@link PgSubmission}. 9 | * 10 | * @author Daniel Sagenschneider 11 | */ 12 | public class ImmediateComplete implements NetworkRequest { 13 | 14 | private final PgSubmission submission; 15 | 16 | public ImmediateComplete(PgSubmission submission) { 17 | this.submission = submission; 18 | } 19 | 20 | @Override 21 | public NetworkRequest write(NetworkWriteContext context) throws Exception { 22 | submission.finish(null); 23 | return null; 24 | } 25 | 26 | } -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/communication/network/Md5PasswordRequest.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.communication.network; 2 | 3 | import java.io.IOException; 4 | import java.nio.charset.StandardCharsets; 5 | import jdk.incubator.sql2.AdbaSessionProperty; 6 | import org.postgresql.adba.communication.FrontendTag; 7 | import org.postgresql.adba.communication.NetworkOutputStream; 8 | import org.postgresql.adba.communication.NetworkRequest; 9 | import org.postgresql.adba.communication.NetworkResponse; 10 | import org.postgresql.adba.communication.NetworkWriteContext; 11 | import org.postgresql.adba.communication.packets.AuthenticationRequest; 12 | import org.postgresql.adba.submissions.ConnectSubmission; 13 | import org.postgresql.adba.util.BinaryHelper; 14 | import org.postgresql.adba.util.PropertyHolder; 15 | 16 | /** 17 | * {@link NetworkRequest} to provide password authentication. 18 | * 19 | * @author Daniel Sagenschneider 20 | */ 21 | public class Md5PasswordRequest implements NetworkRequest { 22 | 23 | private final AuthenticationRequest authentication; 24 | 25 | private final ConnectSubmission connectSubmission; 26 | 27 | public Md5PasswordRequest(AuthenticationRequest authentication, ConnectSubmission connectSubmission) { 28 | this.authentication = authentication; 29 | this.connectSubmission = connectSubmission; 30 | } 31 | 32 | /* 33 | * ==================== NetworkAction ========================== 34 | */ 35 | 36 | @Override 37 | public NetworkRequest write(NetworkWriteContext context) throws IOException { 38 | 39 | // Obtain the properties 40 | PropertyHolder properties = context.getProperties(); 41 | 42 | // Create the payload (TODO determine if can reduce object creation) 43 | String username = (String) properties.get(AdbaSessionProperty.USER); 44 | String password = (String) properties.get(AdbaSessionProperty.PASSWORD); 45 | byte[] content = BinaryHelper.encode(username.getBytes(StandardCharsets.UTF_8), 46 | password.getBytes(StandardCharsets.UTF_8), authentication.getSalt()); 47 | 48 | // Write the request 49 | NetworkOutputStream wire = context.getOutputStream(); 50 | wire.write(FrontendTag.PASSWORD_MESSAGE.getByte()); 51 | wire.initPacket(); 52 | wire.write(content); 53 | wire.writeTerminator(); 54 | wire.completePacket(); 55 | 56 | // No further immediate requests 57 | return null; 58 | } 59 | 60 | @Override 61 | public boolean isBlocking() { 62 | return true; 63 | } 64 | 65 | @Override 66 | public NetworkResponse getRequiredResponse() { 67 | return new AuthenticationResponse(connectSubmission); 68 | } 69 | 70 | } -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/communication/network/ParseRequest.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.communication.network; 2 | 3 | import org.postgresql.adba.communication.FrontendTag; 4 | import org.postgresql.adba.communication.NetworkOutputStream; 5 | import org.postgresql.adba.communication.NetworkRequest; 6 | import org.postgresql.adba.communication.NetworkResponse; 7 | import org.postgresql.adba.communication.NetworkWriteContext; 8 | import org.postgresql.adba.communication.PreparedStatementCache; 9 | import org.postgresql.adba.operations.helpers.ParameterHolder; 10 | import org.postgresql.adba.operations.helpers.QueryParameter; 11 | import org.postgresql.adba.util.BinaryHelper; 12 | 13 | /** 14 | * Row operation {@link NetworkRequest}. 15 | * 16 | * @author Daniel Sagenschneider 17 | */ 18 | public class ParseRequest implements NetworkRequest { 19 | 20 | private final Portal portal; 21 | 22 | public ParseRequest(Portal portal) { 23 | this.portal = portal; 24 | } 25 | 26 | /* 27 | * ================== NetworkRequest ======================== 28 | */ 29 | 30 | @Override 31 | public NetworkRequest write(NetworkWriteContext context) throws Exception { 32 | 33 | // Determine if already query 34 | Query query = portal.getQuery(); 35 | if (query == null) { 36 | 37 | // Obtain the prepared statement cache 38 | PreparedStatementCache cache = context.getPreparedStatementCache(); 39 | 40 | // Obtain the query 41 | String sql = portal.getSql(); 42 | ParameterHolder holder = portal.getParameterHolder(); 43 | query = cache.getQuery(sql, holder.getParamTypes()); 44 | 45 | // Associate query to portal 46 | portal.setQuery(query); 47 | } 48 | 49 | // Determine if prepare query 50 | if ((!query.isParsed()) && (!query.isWaitingParse())) { 51 | 52 | // Obtain the query details 53 | String sql = portal.getSql(); 54 | ParameterHolder holder = portal.getParameterHolder(); 55 | 56 | // Send the prepare packet 57 | NetworkOutputStream wire = context.getOutputStream(); 58 | wire.write(FrontendTag.PARSE.getByte()); 59 | wire.initPacket(); 60 | wire.write(query.getQueryName()); 61 | wire.write(sql); 62 | wire.write(BinaryHelper.writeShort(holder.size())); 63 | for (QueryParameter qp : holder.parameters()) { 64 | wire.write(BinaryHelper.writeInt(qp.getOid())); 65 | } 66 | wire.completePacket(); 67 | } 68 | 69 | // Determine if describe or bind 70 | return new DescribeRequest<>(portal); 71 | 72 | } 73 | 74 | @Override 75 | public NetworkResponse getRequiredResponse() { 76 | Query query = portal.getQuery(); 77 | 78 | // Determine if waiting on parse 79 | if (!query.isWaitingParse()) { 80 | query.flagWaitingParse(); 81 | return new ParseResponse(portal); 82 | } 83 | 84 | // Already waiting on parse 85 | return null; 86 | } 87 | 88 | } -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/communication/network/ParseResponse.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.communication.network; 2 | 3 | import java.io.IOException; 4 | 5 | import org.postgresql.adba.communication.BeFrame; 6 | import org.postgresql.adba.communication.NetworkReadContext; 7 | import org.postgresql.adba.communication.NetworkResponse; 8 | 9 | /** 10 | * Parse {@link NetworkResponse}. 11 | * 12 | * @author Daniel Sagenschneider 13 | */ 14 | public class ParseResponse extends AbstractPortalResponse { 15 | 16 | public ParseResponse(Portal portal) { 17 | super(portal); 18 | } 19 | 20 | @Override 21 | public NetworkResponse read(NetworkReadContext context) throws IOException { 22 | BeFrame frame = context.getBeFrame(); 23 | switch (frame.getTag()) { 24 | 25 | case PARSE_COMPLETE: 26 | portal.getQuery().flagParsed(); 27 | return null; // nothing further 28 | 29 | default: 30 | throw new IllegalStateException("Invalid tag '" + frame.getTag() + "' for " + this.getClass().getSimpleName()); 31 | } 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/communication/network/Query.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.communication.network; 2 | 3 | import java.util.concurrent.atomic.AtomicInteger; 4 | 5 | import org.postgresql.adba.communication.packets.RowDescription; 6 | 7 | /** 8 | * Query. 9 | * 10 | * @author Daniel Sagenschneider 11 | */ 12 | public class Query { 13 | 14 | /** 15 | * Index for unique names. 16 | */ 17 | private static AtomicInteger nameIndex = new AtomicInteger(0); 18 | 19 | /** 20 | * Name for the {@link Query}. 21 | */ 22 | private final String name; 23 | 24 | /** 25 | * Indicates whether parsed. 26 | */ 27 | private boolean isParsed = false; 28 | 29 | /** 30 | * Indicates if waiting parse. 31 | */ 32 | private boolean isAwaitingParse = false; 33 | 34 | /** 35 | * {@link RowDescription}. 36 | */ 37 | private RowDescription rowDescription = null; 38 | 39 | 40 | private boolean canceled; 41 | 42 | /** 43 | * Instantiate. 44 | */ 45 | public Query() { 46 | name = "q" + nameIndex.incrementAndGet(); 47 | } 48 | 49 | /** 50 | * Obtains the name. 51 | * 52 | * @return Name. 53 | */ 54 | public String getQueryName() { 55 | return name; 56 | } 57 | 58 | /** 59 | * Indicates if parsed. 60 | * 61 | * @return Parsed. 62 | */ 63 | public boolean isParsed() { 64 | return isParsed; 65 | } 66 | 67 | /** 68 | * Flags that the query has parsed. 69 | */ 70 | void flagParsed() { 71 | isParsed = true; 72 | } 73 | 74 | /** 75 | * Indicates if waiting on parse. 76 | * 77 | * @return Waiting on parse. 78 | */ 79 | public boolean isWaitingParse() { 80 | return isAwaitingParse; 81 | } 82 | 83 | /** 84 | * Flags that waiting on parse. 85 | */ 86 | void flagWaitingParse() { 87 | isAwaitingParse = true; 88 | } 89 | 90 | /** 91 | * Obtains the {@link RowDescription}. 92 | * 93 | * @return {@link RowDescription}. 94 | */ 95 | RowDescription getRowDescription() { 96 | return rowDescription; 97 | } 98 | 99 | /** 100 | * Specifies the {@link RowDescription}. 101 | * 102 | * @param rowDescription {@link RowDescription}. 103 | */ 104 | void setRowDescription(RowDescription rowDescription) { 105 | this.rowDescription = rowDescription; 106 | } 107 | 108 | public void cancel() { 109 | canceled = true; 110 | } 111 | 112 | public boolean isCanceled() { 113 | return canceled; 114 | } 115 | } -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/communication/network/ReadyForQueryResponse.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.communication.network; 2 | 3 | import org.postgresql.adba.communication.BeFrame; 4 | import org.postgresql.adba.communication.NetworkReadContext; 5 | import org.postgresql.adba.communication.NetworkResponse; 6 | 7 | import java.io.IOException; 8 | 9 | /** 10 | * Ready for query {@link NetworkResponse}. 11 | * 12 | * @author Daniel Sagenschneider 13 | */ 14 | public class ReadyForQueryResponse implements NetworkResponse { 15 | 16 | @Override 17 | public NetworkResponse handleException(Throwable ex) { 18 | throw new IllegalStateException("Ready For Query should not fail", ex); 19 | } 20 | 21 | @Override 22 | public NetworkResponse read(NetworkReadContext context) throws IOException { 23 | BeFrame frame = context.getBeFrame(); 24 | switch (frame.getTag()) { 25 | 26 | case READY_FOR_QUERY: 27 | return null; // Nothing further 28 | 29 | default: 30 | throw new IllegalStateException("Invalid tag '" + frame.getTag() + "' for " + this.getClass().getSimpleName()); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/communication/network/SaslContinueResponse.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.communication.network; 2 | 3 | import org.postgresql.adba.util.scram.client.ScramSession; 4 | import org.postgresql.adba.util.scram.common.exception.ScramException; 5 | import java.io.IOException; 6 | import jdk.incubator.sql2.SqlException; 7 | import org.postgresql.adba.communication.BeFrame; 8 | import org.postgresql.adba.communication.NetworkReadContext; 9 | import org.postgresql.adba.communication.NetworkResponse; 10 | import org.postgresql.adba.communication.packets.AuthenticationRequest; 11 | import org.postgresql.adba.submissions.ConnectSubmission; 12 | 13 | public class SaslContinueResponse implements NetworkResponse { 14 | 15 | private ScramSession scramSession; 16 | private ConnectSubmission connectSubmission; 17 | private ScramSession.ServerFirstProcessor serverFirstProcessor; 18 | 19 | public SaslContinueResponse(ScramSession scramSession, ConnectSubmission connectSubmission) { 20 | this.scramSession = scramSession; 21 | this.connectSubmission = connectSubmission; 22 | } 23 | 24 | @Override 25 | public NetworkResponse read(NetworkReadContext context) throws IOException { 26 | 27 | BeFrame frame = context.getBeFrame(); 28 | switch (frame.getTag()) { 29 | case AUTHENTICATION: 30 | AuthenticationRequest cont = new AuthenticationRequest(frame.getPayload()); 31 | 32 | try { 33 | serverFirstProcessor = scramSession.receiveServerFirstMessage(cont.getSaslContinueMessage()); 34 | 35 | context.write(new SaslFinalPasswordRequest(serverFirstProcessor, connectSubmission)); 36 | return null; 37 | } catch (ScramException e) { 38 | connectSubmission.getCompletionStage().toCompletableFuture().completeExceptionally( 39 | new SqlException(e.getMessage(), e, "not logged in", 0, "", 0)); 40 | return null; 41 | } 42 | 43 | default: 44 | connectSubmission.getCompletionStage().toCompletableFuture().completeExceptionally( 45 | new IllegalStateException("Invalid tag '" + frame.getTag() + "' for " + this.getClass().getSimpleName())); 46 | } 47 | return null; 48 | } 49 | 50 | @Override 51 | public NetworkResponse handleException(Throwable ex) { 52 | return null; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/communication/network/SaslFinalPasswordRequest.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.communication.network; 2 | 3 | import org.postgresql.adba.util.scram.client.ScramSession.ServerFirstProcessor; 4 | import java.nio.charset.StandardCharsets; 5 | import jdk.incubator.sql2.AdbaSessionProperty; 6 | import org.postgresql.adba.communication.FrontendTag; 7 | import org.postgresql.adba.communication.NetworkOutputStream; 8 | import org.postgresql.adba.communication.NetworkRequest; 9 | import org.postgresql.adba.communication.NetworkResponse; 10 | import org.postgresql.adba.communication.NetworkWriteContext; 11 | import org.postgresql.adba.submissions.ConnectSubmission; 12 | import org.postgresql.adba.util.PropertyHolder; 13 | 14 | public class SaslFinalPasswordRequest implements NetworkRequest { 15 | 16 | private ServerFirstProcessor serverFirstProcessor; 17 | private ConnectSubmission connectSubmission; 18 | private org.postgresql.adba.util.scram.client.ScramSession.ClientFinalProcessor clientFinalProcessor; 19 | 20 | public SaslFinalPasswordRequest(ServerFirstProcessor serverFirstProcessor, 21 | ConnectSubmission connectSubmission) { 22 | this.serverFirstProcessor = serverFirstProcessor; 23 | this.connectSubmission = connectSubmission; 24 | } 25 | 26 | @Override 27 | public NetworkRequest write(NetworkWriteContext context) throws Exception { 28 | // Obtain the properties 29 | PropertyHolder properties = context.getProperties(); 30 | 31 | String password = (String) properties.get(AdbaSessionProperty.PASSWORD); 32 | 33 | clientFinalProcessor = serverFirstProcessor.clientFinalProcessor(password); 34 | 35 | String clientFinalMessage = clientFinalProcessor.clientFinalMessage(); 36 | byte[] clientFinalMessageBytes = clientFinalMessage.getBytes(StandardCharsets.UTF_8); 37 | 38 | NetworkOutputStream wire = context.getOutputStream(); 39 | wire.write(FrontendTag.PASSWORD_MESSAGE.getByte()); 40 | wire.initPacket(); 41 | wire.write(clientFinalMessageBytes); 42 | wire.completePacket(); 43 | 44 | // No further immediate requests 45 | return null; 46 | } 47 | 48 | @Override 49 | public boolean isBlocking() { 50 | return true; 51 | } 52 | 53 | @Override 54 | public NetworkResponse getRequiredResponse() { 55 | return new SaslCompleteResponse(connectSubmission, clientFinalProcessor); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/communication/network/SyncRequest.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.communication.network; 2 | 3 | import org.postgresql.adba.communication.FrontendTag; 4 | import org.postgresql.adba.communication.NetworkOutputStream; 5 | import org.postgresql.adba.communication.NetworkRequest; 6 | import org.postgresql.adba.communication.NetworkWriteContext; 7 | 8 | /** 9 | * Sync {@link NetworkRequest}. 10 | * 11 | * @author Daniel Sagenschneider 12 | */ 13 | public class SyncRequest implements NetworkRequest { 14 | private final Portal portal; 15 | 16 | public SyncRequest(Portal portal) { 17 | this.portal = portal; 18 | } 19 | 20 | /* 21 | * ================= NetworkRequest ========================= 22 | */ 23 | 24 | @Override 25 | public NetworkRequest write(NetworkWriteContext context) throws Exception { 26 | 27 | NetworkOutputStream wire = context.getOutputStream(); 28 | wire.write(FrontendTag.SYNC.getByte()); 29 | wire.initPacket(); 30 | wire.completePacket(); 31 | 32 | if (portal.hasMoreToExecute()) { 33 | return new BindRequest<>(portal); 34 | } 35 | 36 | // Nothing further 37 | return null; 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/communication/packets/ErrorPacket.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.communication.packets; 2 | 3 | import org.postgresql.adba.communication.packets.parts.ErrorResponseField; 4 | import org.postgresql.adba.util.BinaryHelper; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | public class ErrorPacket extends Exception { 10 | 11 | private static List parseFields(byte[] payload) { 12 | List fields = new ArrayList<>(); 13 | List nullPositions = new ArrayList<>(); 14 | 15 | for (int i = 0; i < payload.length; i++) { 16 | if (payload[i] == 0) { 17 | nullPositions.add(i); 18 | } 19 | } 20 | 21 | for (int i = 0; i < nullPositions.size() - 2; i++) { 22 | fields.add(new ErrorResponseField(ErrorResponseField.Types.lookup(payload[nullPositions.get(i) + 1]), 23 | new String(BinaryHelper.subBytes(payload, nullPositions.get(i) + 2, nullPositions.get(i + 1))))); 24 | } 25 | return fields; 26 | } 27 | 28 | private static String getField(ErrorResponseField.Types type, List fields) { 29 | for (ErrorResponseField field : fields) { 30 | if (type == field.getType()) { 31 | return field.getMessage(); 32 | } 33 | } 34 | 35 | return null; 36 | } 37 | 38 | private List fields; 39 | 40 | public ErrorPacket(byte[] payload) { 41 | this(parseFields(payload)); 42 | } 43 | 44 | private ErrorPacket(List fields) { 45 | super(getField(ErrorResponseField.Types.MESSAGE, fields)); 46 | this.fields = fields; 47 | } 48 | 49 | public List getFields() { 50 | return fields; 51 | } 52 | 53 | /** 54 | * returns the message of the field that matches the type. 55 | * @param type type to search for 56 | * @return message of field 57 | */ 58 | public String getField(ErrorResponseField.Types type) { 59 | for (ErrorResponseField field : fields) { 60 | if (type == field.getType()) { 61 | return field.getMessage(); 62 | } 63 | } 64 | 65 | return null; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/communication/packets/ParameterStatus.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.communication.packets; 2 | 3 | import org.postgresql.adba.util.BinaryHelper; 4 | 5 | public class ParameterStatus { 6 | private String name; 7 | private String value; 8 | 9 | /** 10 | * parses the parameter status. 11 | * @param payload bytes from the server to parse 12 | */ 13 | public ParameterStatus(byte[] payload) { 14 | int firstNullPos = 0; 15 | int secondNullPos = 0; 16 | 17 | for (int i = 0; i < payload.length; i++) { 18 | if (payload[i] == 0) { 19 | firstNullPos = i; 20 | break; 21 | } 22 | } 23 | 24 | for (int i = firstNullPos; i < payload.length; i++) { 25 | if (payload[i] == 0) { 26 | secondNullPos = i; 27 | break; 28 | } 29 | } 30 | 31 | name = new String(BinaryHelper.subBytes(payload, 0, firstNullPos)); 32 | value = new String(BinaryHelper.subBytes(payload, firstNullPos, secondNullPos)); 33 | } 34 | 35 | public String getName() { 36 | return name; 37 | } 38 | 39 | public String getValue() { 40 | return value; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/communication/packets/ReadyForQuery.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.communication.packets; 2 | 3 | public class ReadyForQuery { 4 | public enum TransactionStatus { 5 | IDLE('I'), 6 | OPEN('T'), 7 | FAILED('E'); 8 | 9 | private byte code; 10 | 11 | TransactionStatus(char code) { 12 | this.code = (byte)code; 13 | } 14 | 15 | /** 16 | * find the transaction status that matches the supplied byte. 17 | * @param b byte to search for 18 | * @return the matching TransactionStatus 19 | */ 20 | public static TransactionStatus lookup(byte b) { 21 | for (TransactionStatus ts : values()) { 22 | if (ts.code == b) { 23 | return ts; 24 | } 25 | } 26 | 27 | throw new IllegalArgumentException("unknown ready for query packet tag: " + b); 28 | } 29 | } 30 | 31 | private TransactionStatus transactionStatus; 32 | 33 | public ReadyForQuery(byte[] payload) { 34 | this.transactionStatus = TransactionStatus.lookup(payload[0]); 35 | } 36 | 37 | public TransactionStatus getTransactionStatus() { 38 | return transactionStatus; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/communication/packets/RowDescription.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.communication.packets; 2 | 3 | import org.postgresql.adba.communication.packets.parts.ColumnDescription; 4 | import org.postgresql.adba.util.BinaryHelper; 5 | 6 | import java.nio.charset.StandardCharsets; 7 | 8 | public class RowDescription { 9 | private ColumnDescription[] descriptions; 10 | 11 | /** 12 | * parses a sequence of bytes in to a RowDescription object. 13 | * 14 | * @param bytes bytes to parse 15 | */ 16 | public RowDescription(byte[] bytes) { 17 | short numOfColumns = BinaryHelper.readShort(bytes[0], bytes[1]); 18 | int pos = 2; 19 | descriptions = new ColumnDescription[numOfColumns]; 20 | for (int i = 0; i < numOfColumns; i++) { 21 | int nameEnd = BinaryHelper.nextNullBytePos(bytes, pos); 22 | String name = new String(BinaryHelper.subBytes(bytes, pos, nameEnd), StandardCharsets.UTF_8); 23 | pos = nameEnd + 1; 24 | int objectIdOfTable = BinaryHelper.readInt(bytes[pos], bytes[pos + 1], bytes[pos + 2], bytes[pos + 3]); 25 | pos += 4; 26 | short attributeNumberOfColumn = BinaryHelper.readShort(bytes[pos], bytes[pos + 1]); 27 | pos += 2; 28 | int fieldOId = BinaryHelper.readInt(bytes[pos], bytes[pos + 1], bytes[pos + 2], bytes[pos + 3]); 29 | pos += 4; 30 | short dataTypeSize = BinaryHelper.readShort(bytes[pos], bytes[pos + 1]); 31 | pos += 2; 32 | int typeModifier = BinaryHelper.readInt(bytes[pos], bytes[pos + 1], bytes[pos + 2], bytes[pos + 3]); 33 | pos += 4; 34 | short formatCode = BinaryHelper.readShort(bytes[pos], bytes[pos + 1]); 35 | pos += 2; 36 | 37 | descriptions[i] = new ColumnDescription(name, objectIdOfTable, attributeNumberOfColumn, fieldOId, 38 | dataTypeSize, typeModifier, formatCode); 39 | } 40 | } 41 | 42 | public ColumnDescription[] getDescriptions() { 43 | return descriptions; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/communication/packets/parts/ColumnDescription.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.communication.packets.parts; 2 | 3 | public class ColumnDescription { 4 | private String name; 5 | private int objectIdOfTable; 6 | private short attributeNumberOfColumn; 7 | private ColumnTypes columnType; 8 | private short dataTypeSize; 9 | private int typeModifier; 10 | private FormatCodeTypes formatCode; 11 | 12 | /** 13 | * Represents a description of a column in a result set. 14 | * 15 | * @param name name of the column 16 | * @param objectIdOfTable the oid of the table 17 | * @param attributeNumberOfColumn the column number 18 | * @param fieldOId the oid of the field 19 | * @param dataTypeSize the size of the data type 20 | * @param typeModifier type modifier 21 | * @param formatCode format code 22 | */ 23 | public ColumnDescription(String name, int objectIdOfTable, short attributeNumberOfColumn, int fieldOId, 24 | short dataTypeSize, int typeModifier, short formatCode) { 25 | this.name = name; 26 | this.objectIdOfTable = objectIdOfTable; 27 | this.attributeNumberOfColumn = attributeNumberOfColumn; 28 | this.columnType = ColumnTypes.lookup(fieldOId); 29 | this.dataTypeSize = dataTypeSize; 30 | this.typeModifier = typeModifier; 31 | this.formatCode = FormatCodeTypes.lookup(formatCode); 32 | } 33 | 34 | public String getName() { 35 | return name; 36 | } 37 | 38 | public int getObjectIdOfTable() { 39 | return objectIdOfTable; 40 | } 41 | 42 | public short getAttributeNumberOfColumn() { 43 | return attributeNumberOfColumn; 44 | } 45 | 46 | public ColumnTypes getColumnType() { 47 | return columnType; 48 | } 49 | 50 | public short getDataTypeSize() { 51 | return dataTypeSize; 52 | } 53 | 54 | public int getTypeModifier() { 55 | return typeModifier; 56 | } 57 | 58 | public FormatCodeTypes getFormatCode() { 59 | return formatCode; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/communication/packets/parts/FormatCodeTypes.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.communication.packets.parts; 2 | 3 | public enum FormatCodeTypes { 4 | TEXT((short)0), 5 | BINARY((short)1); 6 | 7 | private short code; 8 | 9 | FormatCodeTypes(short code) { 10 | this.code = code; 11 | } 12 | 13 | /** 14 | * Finds the format code for the short value. 15 | * @param code either 0 or 1 is allowed 16 | * @return returns TEXT or BINARY 17 | */ 18 | public static FormatCodeTypes lookup(short code) { 19 | for (FormatCodeTypes type : values()) { 20 | if (code == type.code) { 21 | return type; 22 | } 23 | } 24 | 25 | throw new IllegalArgumentException("no FormatType with code: " + code); 26 | } 27 | 28 | public short getCode() { 29 | return code; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/execution/NioLoop.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.execution; 2 | 3 | import jdk.incubator.sql2.Operation; 4 | 5 | import java.io.IOException; 6 | import java.nio.channels.SelectableChannel; 7 | import java.nio.channels.Selector; 8 | 9 | /** 10 | * Provides an event loop for servicing communication. 11 | * 12 | *

This allows plugging in different {@link NioLoop} implementations. For 13 | * example, the same {@link Selector} can be used for both asynchronous database 14 | * {@link Operation} and HTTP servicing by the web application. 15 | * 16 | * @author Daniel Sagenschneider 17 | */ 18 | public interface NioLoop { 19 | 20 | /** 21 | * Registers an {@link NioService}. 22 | * 23 | * @param channel {@link SelectableChannel}. 24 | * @param nioServiceFactory {@link NioServiceFactory} to create the 25 | * {@link NioService}. 26 | * @return {@link NioService} registered. 27 | * @throws IOException If fails to register {@link NioService}. 28 | */ 29 | NioService registerNioService(SelectableChannel channel, NioServiceFactory nioServiceFactory) throws IOException; 30 | 31 | } -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/execution/NioService.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.execution; 2 | 3 | import java.nio.channels.Channel; 4 | 5 | /** 6 | * NIO service for the {@link NioLoop}. 7 | * 8 | * @author Daniel Sagenschneider 9 | */ 10 | public interface NioService { 11 | 12 | /** 13 | * Handles the connect. 14 | * 15 | * @throws Exception If fails to handle the accept. 16 | */ 17 | void handleConnect() throws Exception; 18 | 19 | /** 20 | * Indicates data is available to read. 21 | * 22 | * @throws Exception If failure in reading and processing the data. 23 | */ 24 | void handleRead() throws Exception; 25 | 26 | /** 27 | * Indicates underlying {@link Channel} has cleared space for further writing. 28 | * 29 | * @throws Exception If failure in writing data. 30 | */ 31 | void handleWrite() throws Exception; 32 | 33 | /** 34 | * Handles a {@link Throwable} in servicing. 35 | * 36 | * @param ex {@link Throwable} to be handled. 37 | */ 38 | void handleException(Throwable ex); 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/execution/NioServiceContext.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.execution; 2 | 3 | import java.io.IOException; 4 | import java.nio.channels.SelectableChannel; 5 | import java.nio.channels.SelectionKey; 6 | 7 | /** 8 | * Context for the {@link NioService}. 9 | * 10 | * @author Daniel Sagenschneider 11 | */ 12 | public interface NioServiceContext { 13 | 14 | /** 15 | * Obtains the {@link SelectableChannel}. 16 | * 17 | * @return {@link SelectableChannel}. 18 | */ 19 | SelectableChannel getChannel(); 20 | 21 | /** 22 | * Flags that a write is required. 23 | */ 24 | void writeRequired(); 25 | 26 | /** 27 | * Sets the interested operations as per {@link SelectionKey}. 28 | * 29 | * @param interestedOps Interested operations as per {@link SelectionKey}. 30 | * @throws IOException If fails to set operations. 31 | */ 32 | void setInterestedOps(int interestedOps) throws IOException; 33 | 34 | /** 35 | * Unregisters from the {@link NioLoop}. 36 | * 37 | * @throws IOException If fails to unregister. 38 | */ 39 | void unregister() throws IOException; 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/execution/NioServiceFactory.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.execution; 2 | 3 | import java.io.IOException; 4 | 5 | /** 6 | * Factory to create the {@link NioService}. 7 | * 8 | * @author Daniel Sagenschneider 9 | */ 10 | public interface NioServiceFactory { 11 | 12 | /** 13 | * Creates the {@link NioService}. 14 | * 15 | * @param context {@link NioServiceContext}. 16 | * @return {@link NioService}. 17 | * @throws IOException If fails to create the {@link NioService}. 18 | */ 19 | NioService createNioService(NioServiceContext context) throws IOException; 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/operations/PgCatchOperation.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.operations; 2 | 3 | import jdk.incubator.sql2.PrimitiveOperation; 4 | import jdk.incubator.sql2.Submission; 5 | import org.postgresql.adba.PgSession; 6 | import org.postgresql.adba.PgSubmission; 7 | import org.postgresql.adba.submissions.BaseSubmission; 8 | 9 | public class PgCatchOperation implements PrimitiveOperation { 10 | private PgSession connection; 11 | 12 | public PgCatchOperation(PgSession connection) { 13 | this.connection = connection; 14 | } 15 | 16 | @Override 17 | public Submission submit() { 18 | BaseSubmission submission = new BaseSubmission<>(this::cancel, PgSubmission.Types.CATCH, null, null, null, null); 19 | connection.submit(submission); 20 | return submission; 21 | } 22 | 23 | boolean cancel() { 24 | // todo set life cycle to canceled 25 | return true; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/operations/PgCloseOperation.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.operations; 2 | 3 | import jdk.incubator.sql2.Operation; 4 | import jdk.incubator.sql2.Submission; 5 | import org.postgresql.adba.PgSession; 6 | import org.postgresql.adba.communication.NetworkConnection; 7 | import org.postgresql.adba.communication.network.CloseRequest; 8 | import org.postgresql.adba.submissions.CloseSubmission; 9 | 10 | import java.time.Duration; 11 | import java.util.function.Consumer; 12 | 13 | public class PgCloseOperation implements Operation { 14 | private PgSession connection; 15 | private Consumer errorHandler; 16 | private NetworkConnection protocol; 17 | 18 | public PgCloseOperation(PgSession connection, NetworkConnection protocol) { 19 | this.connection = connection; 20 | this.protocol = protocol; 21 | } 22 | 23 | @Override 24 | public Operation onError(Consumer errorHandler) { 25 | if (this.errorHandler != null) { 26 | throw new IllegalStateException("you are not allowed to call onError multiple times"); 27 | } 28 | 29 | this.errorHandler = errorHandler; 30 | return this; 31 | } 32 | 33 | @Override 34 | public Operation timeout(Duration minTime) { 35 | return this; 36 | } 37 | 38 | @Override 39 | public Submission submit() { 40 | CloseSubmission submission = new CloseSubmission(this::cancel, errorHandler); 41 | submission.getCompletionStage().thenAccept(s -> connection.setLifeCycleClosed()); 42 | CloseRequest closeRequest = new CloseRequest(submission); 43 | protocol.sendNetworkRequest(closeRequest); 44 | 45 | // Closing so unregister connection 46 | this.connection.unregister(); 47 | 48 | return submission; 49 | } 50 | 51 | private boolean cancel() { 52 | // todo set life cycle to canceled 53 | return true; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/operations/PgConnectOperation.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.operations; 2 | 3 | import java.time.Duration; 4 | import java.util.function.Consumer; 5 | import jdk.incubator.sql2.Operation; 6 | import jdk.incubator.sql2.Submission; 7 | import org.postgresql.adba.PgSession; 8 | import org.postgresql.adba.communication.NetworkConnection; 9 | import org.postgresql.adba.submissions.ConnectSubmission; 10 | import org.postgresql.adba.submissions.GroupSubmission; 11 | 12 | public class PgConnectOperation implements Operation { 13 | 14 | private Consumer errorHandler; 15 | private Duration minTime; 16 | private PgSession connection; 17 | private GroupSubmission groupSubmission; 18 | private NetworkConnection protocol; 19 | 20 | /** 21 | * Initialize. 22 | * @param connection the session that created this Operation 23 | * @param groupSubmission if the operation is part of a group 24 | * @param protocol network link 25 | */ 26 | public PgConnectOperation(PgSession connection, GroupSubmission groupSubmission, NetworkConnection protocol) { 27 | this.connection = connection; 28 | this.groupSubmission = groupSubmission; 29 | this.protocol = protocol; 30 | } 31 | 32 | @Override 33 | public Operation onError(Consumer errorHandler) { 34 | if (this.errorHandler != null) { 35 | throw new IllegalStateException("you are not allowed to call onError multiple times"); 36 | } 37 | 38 | this.errorHandler = errorHandler; 39 | return this; 40 | } 41 | 42 | @Override 43 | public Operation timeout(Duration minTime) { 44 | this.minTime = minTime; 45 | return this; 46 | } 47 | 48 | @Override 49 | public Submission submit() { 50 | ConnectSubmission submission = new ConnectSubmission(this::cancel, errorHandler, groupSubmission, connection.getProperties()); 51 | submission.getCompletionStage().thenAccept(s -> { 52 | connection.setLifeCycleOpen(); 53 | }); 54 | protocol.sendNetworkConnect(submission.getNetworkConnect()); 55 | 56 | return submission; 57 | } 58 | 59 | boolean cancel() { 60 | // todo set life cycle to canceled 61 | return true; 62 | } 63 | 64 | } -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/operations/PgLocalOperation.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.operations; 2 | 3 | import jdk.incubator.sql2.LocalOperation; 4 | import jdk.incubator.sql2.Submission; 5 | import org.postgresql.adba.PgSession; 6 | import org.postgresql.adba.PgSubmission; 7 | import org.postgresql.adba.submissions.GroupSubmission; 8 | import org.postgresql.adba.submissions.LocalSubmission; 9 | 10 | import java.time.Duration; 11 | import java.util.concurrent.Callable; 12 | import java.util.function.Consumer; 13 | 14 | public class PgLocalOperation implements LocalOperation { 15 | private static final Callable defaultAction = () -> { 16 | return null; 17 | }; 18 | private PgSession connection; 19 | private Callable action = defaultAction; 20 | private Consumer errorHandler; 21 | private GroupSubmission groupSubmission; 22 | 23 | public PgLocalOperation(PgSession connection, GroupSubmission groupSubmission) { 24 | this.connection = connection; 25 | this.groupSubmission = groupSubmission; 26 | } 27 | 28 | @Override 29 | public LocalOperation onExecution(Callable action) { 30 | if (action != null) { 31 | this.action = action; 32 | } 33 | return this; 34 | } 35 | 36 | @Override 37 | public LocalOperation onError(Consumer errorHandler) { 38 | if (this.errorHandler != null) { 39 | throw new IllegalStateException("you are not allowed to call onError multiple times"); 40 | } 41 | 42 | this.errorHandler = errorHandler; 43 | return this; 44 | } 45 | 46 | @Override 47 | public LocalOperation timeout(Duration minTime) { 48 | return this; 49 | } 50 | 51 | @Override 52 | public Submission submit() { 53 | PgSubmission submission = new LocalSubmission<>(this::cancel, errorHandler, action, groupSubmission); 54 | connection.submit(submission); 55 | return submission; 56 | } 57 | 58 | private boolean cancel() { 59 | // todo set life cycle to canceled 60 | return true; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/operations/PgOperation.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.operations; 2 | 3 | import jdk.incubator.sql2.Operation; 4 | import jdk.incubator.sql2.Submission; 5 | import org.postgresql.adba.PgSession; 6 | import org.postgresql.adba.PgSubmission; 7 | import org.postgresql.adba.operations.helpers.ParameterHolder; 8 | import org.postgresql.adba.submissions.VoidSubmission; 9 | 10 | import java.time.Duration; 11 | import java.util.function.Consumer; 12 | 13 | public class PgOperation implements Operation { 14 | private final PgSession connection; 15 | private final String sql; 16 | private Consumer errorHandler; 17 | 18 | public PgOperation(PgSession connection, String sql) { 19 | this.connection = connection; 20 | this.sql = sql; 21 | } 22 | 23 | @Override 24 | public Operation onError(Consumer errorHandler) { 25 | if (this.errorHandler != null) { 26 | throw new IllegalStateException("you are not allowed to call onError multiple times"); 27 | } 28 | 29 | this.errorHandler = errorHandler; 30 | return this; 31 | } 32 | 33 | @Override 34 | public Operation timeout(Duration minTime) { 35 | return this; 36 | } 37 | 38 | @Override 39 | public Submission submit() { 40 | PgSubmission submission = new VoidSubmission<>(this::cancel, errorHandler, new ParameterHolder(), null, sql); 41 | connection.submit(submission); 42 | return submission; 43 | } 44 | 45 | private boolean cancel() { 46 | // todo set life cycle to canceled 47 | return true; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/operations/PgRowOperation.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.operations; 2 | 3 | import jdk.incubator.sql2.Operation; 4 | import jdk.incubator.sql2.Result; 5 | import jdk.incubator.sql2.RowOperation; 6 | import jdk.incubator.sql2.Submission; 7 | import org.postgresql.adba.PgSubmission; 8 | import org.postgresql.adba.submissions.BaseSubmission; 9 | 10 | import java.time.Duration; 11 | import java.util.ArrayList; 12 | import java.util.HashMap; 13 | import java.util.List; 14 | import java.util.Map; 15 | import java.util.function.Consumer; 16 | import java.util.stream.Collector; 17 | 18 | public class PgRowOperation implements RowOperation { 19 | private static final Collector>, List>> defaultCollector = 20 | Collector.of( 21 | () -> new ArrayList<>(), 22 | (a, v) -> { 23 | Map row = new HashMap<>(); 24 | v.forEach(column -> row.put(column.identifier(), v.get(Object.class))); 25 | a.add(row); 26 | }, 27 | (a, b) -> null, 28 | a -> a); 29 | 30 | private PgRowCountOperation parentOperation; 31 | private Consumer errorHandler; 32 | private Collector collector = defaultCollector; 33 | 34 | public PgRowOperation(PgRowCountOperation parentOperation, String... keys) { 35 | this.parentOperation = parentOperation; 36 | } 37 | 38 | @Override 39 | public RowOperation fetchSize(long rows) throws IllegalArgumentException { 40 | return this; 41 | } 42 | 43 | @Override 44 | public RowOperation collect(Collector c) { 45 | this.collector = c; 46 | return this; 47 | } 48 | 49 | @Override 50 | public RowOperation onError(Consumer errorHandler) { 51 | this.errorHandler = errorHandler; 52 | return this; 53 | } 54 | 55 | @Override 56 | public Operation timeout(Duration minTime) { 57 | return this; 58 | } 59 | 60 | @Override 61 | public Submission submit() { 62 | PgSubmission submission = new BaseSubmission<>(this::cancel, PgSubmission.Types.ROW, errorHandler, null, null, null); 63 | submission.setCollector(collector); 64 | parentOperation.addReturningRowSubmission(submission); 65 | return submission; 66 | } 67 | 68 | private boolean cancel() { 69 | // todo set life cycle to canceled 70 | return true; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/operations/PgTransactionOperation.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.operations; 2 | 3 | import java.time.Duration; 4 | import java.util.function.Consumer; 5 | import jdk.incubator.sql2.Operation; 6 | import jdk.incubator.sql2.Submission; 7 | import jdk.incubator.sql2.TransactionCompletion; 8 | import jdk.incubator.sql2.TransactionOutcome; 9 | import org.postgresql.adba.PgSession; 10 | import org.postgresql.adba.PgSubmission; 11 | import org.postgresql.adba.submissions.TransactionSubmission; 12 | 13 | public class PgTransactionOperation implements Operation { 14 | private TransactionCompletion transaction; 15 | private PgSession connection; 16 | private Consumer errorHandler; 17 | 18 | public PgTransactionOperation(TransactionCompletion transaction, PgSession connection) { 19 | this.transaction = transaction; 20 | this.connection = connection; 21 | } 22 | 23 | @Override 24 | public Operation onError(Consumer errorHandler) { 25 | if (this.errorHandler != null) { 26 | throw new IllegalStateException("you are not allowed to call onError multiple times"); 27 | } 28 | 29 | this.errorHandler = errorHandler; 30 | return this; 31 | } 32 | 33 | @Override 34 | public Operation timeout(Duration minTime) { 35 | return this; 36 | } 37 | 38 | @Override 39 | public Submission submit() { 40 | String sql; 41 | if (transaction.isRollbackOnly()) { 42 | sql = "ROLLBACK TRANSACTION"; 43 | } else { 44 | sql = "COMMIT TRANSACTION"; 45 | } 46 | PgSubmission submission = new TransactionSubmission(this::cancel, errorHandler, sql); 47 | connection.submit(submission); 48 | return submission; 49 | } 50 | 51 | boolean cancel() { 52 | // todo set life cycle to canceled 53 | return true; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/operations/helpers/ArrayQueryParameter.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.operations.helpers; 2 | 3 | import jdk.incubator.sql2.SqlType; 4 | import org.postgresql.adba.communication.packets.parts.PgAdbaType; 5 | 6 | import java.util.List; 7 | import java.util.Objects; 8 | import java.util.concurrent.ExecutionException; 9 | 10 | public class ArrayQueryParameter implements QueryParameter { 11 | private PgAdbaType type; 12 | private List values; 13 | 14 | /** 15 | * If a parameter needs an array of values, in order to repeat the query multiple times. 16 | * @param values the values 17 | */ 18 | public ArrayQueryParameter(List values) { 19 | this.values = values; 20 | 21 | Object value = firstNonNull(values); 22 | if (value == null) { 23 | type = PgAdbaType.NULL; 24 | } else { 25 | type = PgAdbaType.guessTypeFromClass(value.getClass()); 26 | } 27 | } 28 | 29 | /** 30 | * If a parameter needs an array of values, in order to repeat the query multiple times. 31 | * @param values the values 32 | * @param type the type these values have 33 | */ 34 | public ArrayQueryParameter(List values, SqlType type) { 35 | this.values = values; 36 | if (type != null) { 37 | this.type = PgAdbaType.convert(type); 38 | } else { 39 | Object value = firstNonNull(values); 40 | if (value == null) { 41 | this.type = PgAdbaType.NULL; 42 | } else { 43 | this.type = PgAdbaType.guessTypeFromClass(value.getClass()); 44 | } 45 | } 46 | } 47 | 48 | private Object firstNonNull(List values) { 49 | return values.stream().filter(Objects::nonNull).findFirst(); 50 | } 51 | 52 | @Override 53 | public int getOid() { 54 | return type.getOid(); 55 | } 56 | 57 | @Override 58 | public short getParameterFormatCode() { 59 | return type.getFormatCodeTypes().getCode(); 60 | } 61 | 62 | @Override 63 | public byte[] getParameter(int index) throws ExecutionException, InterruptedException { 64 | return type.getByteGenerator().apply(values.get(index)); 65 | } 66 | 67 | @Override 68 | public int numberOfQueryRepetitions() { 69 | return values.size(); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/operations/helpers/FutureQueryParameter.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.operations.helpers; 2 | 3 | import jdk.incubator.sql2.SqlType; 4 | import org.postgresql.adba.communication.packets.parts.PgAdbaType; 5 | 6 | import java.util.concurrent.CompletionStage; 7 | import java.util.concurrent.ExecutionException; 8 | 9 | public class FutureQueryParameter implements QueryParameter { 10 | private PgAdbaType type; 11 | private Object value; 12 | private CompletionStage valueHolder; 13 | 14 | public FutureQueryParameter(CompletionStage valueHolder) { 15 | this.valueHolder = valueHolder; 16 | } 17 | 18 | public FutureQueryParameter(CompletionStage valueHolder, SqlType type) { 19 | this.valueHolder = valueHolder; 20 | this.type = PgAdbaType.convert(type); 21 | } 22 | 23 | private void resolveType() throws ExecutionException, InterruptedException { 24 | if (type == null && value == null && valueHolder == null) { 25 | type = PgAdbaType.NULL; 26 | } else if (type == null && valueHolder != null) { 27 | value = valueHolder.toCompletableFuture().get(); 28 | valueHolder = null; 29 | 30 | if (value == null) { 31 | type = PgAdbaType.NULL; 32 | } else { 33 | type = PgAdbaType.guessTypeFromClass(value.getClass()); 34 | } 35 | } 36 | 37 | } 38 | 39 | @Override 40 | public int getOid() throws ExecutionException, InterruptedException { 41 | resolveType(); 42 | 43 | return type.getOid(); 44 | } 45 | 46 | @Override 47 | public short getParameterFormatCode() throws ExecutionException, InterruptedException { 48 | resolveType(); 49 | 50 | return type.getFormatCodeTypes().getCode(); 51 | } 52 | 53 | @Override 54 | public byte[] getParameter(int index) throws ExecutionException, InterruptedException { 55 | if (valueHolder != null) { 56 | return type.getByteGenerator().apply(valueHolder.toCompletableFuture().get()); 57 | } else { 58 | return type.getByteGenerator().apply(value); 59 | } 60 | } 61 | 62 | @Override 63 | public int numberOfQueryRepetitions() { 64 | return 1; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/operations/helpers/ParameterHolder.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.operations.helpers; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collection; 5 | import java.util.List; 6 | import java.util.Map; 7 | import java.util.TreeMap; 8 | import java.util.concurrent.ExecutionException; 9 | 10 | public class ParameterHolder { 11 | private Map parameterMap = new TreeMap<>(); 12 | 13 | public short size() { 14 | return (short) parameterMap.size(); 15 | } 16 | 17 | public Collection parameters() { 18 | return parameterMap.values(); 19 | } 20 | 21 | /** 22 | * When the user adds parameters they gets stored by this method. 23 | * 24 | * @param id parameter id string, on the format $1 25 | * @param queryParameter the parameter, either the value or an future 26 | */ 27 | public void add(String id, QueryParameter queryParameter) { 28 | try { 29 | parameterMap.put(Integer.parseInt(id.substring(1)), queryParameter); 30 | } catch (NumberFormatException e) { 31 | throw new IllegalArgumentException("the names of parameter placeholders must be on the format: " 32 | + "$ with the numbers starting at 1 and increasing by 1 for each parameter", e); 33 | } 34 | } 35 | 36 | /** 37 | * get a list of oid's for the parameters for this query. 38 | * @return a list of oid's 39 | * @throws ExecutionException if the parameters are futures that throw during resolving 40 | * @throws InterruptedException if the parameters are futures that throw during resolving 41 | */ 42 | public List getParamTypes() throws ExecutionException, InterruptedException { 43 | List types = new ArrayList<>(); 44 | 45 | for (Map.Entry entry : parameterMap.entrySet()) { 46 | types.add(entry.getValue().getOid()); 47 | } 48 | 49 | return types; 50 | } 51 | 52 | /** 53 | * some operations repeats, and those have lists of parameters instead of just values. 54 | * @return the number of repetitions 55 | * @throws ExecutionException if the parameters are futures that throw during resolving 56 | * @throws InterruptedException if the parameters are futures that throw during resolving 57 | */ 58 | public int numberOfQueryRepetitions() throws ExecutionException, InterruptedException { 59 | if (parameterMap.size() == 0) { 60 | return 1; 61 | } 62 | 63 | return parameterMap.entrySet().iterator().next().getValue().numberOfQueryRepetitions(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/operations/helpers/PgTransaction.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.operations.helpers; 2 | 3 | import jdk.incubator.sql2.TransactionCompletion; 4 | 5 | public class PgTransaction implements TransactionCompletion { 6 | private boolean rollbackOnly; 7 | 8 | @Override 9 | public boolean setRollbackOnly() { 10 | return rollbackOnly = true; 11 | } 12 | 13 | @Override 14 | public boolean isRollbackOnly() { 15 | return rollbackOnly; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/operations/helpers/QueryParameter.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.operations.helpers; 2 | 3 | import java.util.concurrent.ExecutionException; 4 | 5 | public interface QueryParameter { 6 | int getOid() throws ExecutionException, InterruptedException; 7 | 8 | short getParameterFormatCode() throws ExecutionException, InterruptedException; 9 | 10 | byte[] getParameter(int index) throws ExecutionException, InterruptedException; 11 | 12 | int numberOfQueryRepetitions() throws ExecutionException, InterruptedException; 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/operations/helpers/ValueQueryParameter.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.operations.helpers; 2 | 3 | import jdk.incubator.sql2.SqlType; 4 | import org.postgresql.adba.communication.packets.parts.PgAdbaType; 5 | 6 | public class ValueQueryParameter implements QueryParameter { 7 | private PgAdbaType type; 8 | private Object value; 9 | 10 | /** 11 | * parameter that represent one value. 12 | * @param value the value 13 | */ 14 | public ValueQueryParameter(Object value) { 15 | this.value = value; 16 | 17 | if (value == null) { 18 | type = PgAdbaType.NULL; 19 | } else { 20 | type = PgAdbaType.guessTypeFromClass(value.getClass()); 21 | } 22 | } 23 | 24 | /** 25 | * parameter that represent one value. 26 | * @param value the value 27 | * @param type the type of the value 28 | */ 29 | public ValueQueryParameter(Object value, SqlType type) { 30 | this.value = value; 31 | if (type != null) { 32 | this.type = PgAdbaType.convert(type); 33 | } else { 34 | if (value == null) { 35 | this.type = PgAdbaType.NULL; 36 | } else { 37 | this.type = PgAdbaType.guessTypeFromClass(value.getClass()); 38 | } 39 | } 40 | } 41 | 42 | @Override 43 | public int getOid() { 44 | return type.getOid(); 45 | } 46 | 47 | @Override 48 | public short getParameterFormatCode() { 49 | return type.getFormatCodeTypes().getCode(); 50 | } 51 | 52 | @Override 53 | public byte[] getParameter(int index) { 54 | return type.getByteGenerator().apply(value); 55 | } 56 | 57 | @Override 58 | public int numberOfQueryRepetitions() { 59 | return 1; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/pgdatatypes/Box.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.pgdatatypes; 2 | 3 | import java.util.Objects; 4 | 5 | public class Box implements Comparable { 6 | private double x1; 7 | private double y1; 8 | private double x2; 9 | private double y2; 10 | 11 | /** 12 | * Represent a box defined by two points. 13 | * 14 | * @param x1 first point x 15 | * @param y1 first point y 16 | * @param x2 second point x 17 | * @param y2 second point y 18 | */ 19 | public Box(double x1, double y1, double x2, double y2) { 20 | this.x1 = x1; 21 | this.y1 = y1; 22 | this.x2 = x2; 23 | this.y2 = y2; 24 | } 25 | 26 | public double getX1() { 27 | return x1; 28 | } 29 | 30 | public void setX1(double x1) { 31 | this.x1 = x1; 32 | } 33 | 34 | public double getY1() { 35 | return y1; 36 | } 37 | 38 | public void setY1(double y1) { 39 | this.y1 = y1; 40 | } 41 | 42 | public double getX2() { 43 | return x2; 44 | } 45 | 46 | public void setX2(double x2) { 47 | this.x2 = x2; 48 | } 49 | 50 | public double getY2() { 51 | return y2; 52 | } 53 | 54 | public void setY2(double y2) { 55 | this.y2 = y2; 56 | } 57 | 58 | @Override 59 | public boolean equals(Object o) { 60 | if (this == o) { 61 | return true; 62 | } 63 | if (o == null || getClass() != o.getClass()) { 64 | return false; 65 | } 66 | Box that = (Box) o; 67 | return Double.compare(that.x1, x1) == 0 68 | && Double.compare(that.y1, y1) == 0 69 | && Double.compare(that.x2, x2) == 0 70 | && Double.compare(that.y2, y2) == 0; 71 | } 72 | 73 | @Override 74 | public int hashCode() { 75 | return Objects.hash(x1, y1, x2, y2); 76 | } 77 | 78 | @Override 79 | public int compareTo(Box ls) { 80 | int c = Double.compare(ls.x1, x1); 81 | 82 | if (c != 0) { 83 | return c; 84 | } 85 | 86 | c = Double.compare(ls.y1, y1); 87 | 88 | if (c != 0) { 89 | return c; 90 | } 91 | 92 | c = Double.compare(ls.x2, x2); 93 | 94 | if (c != 0) { 95 | return c; 96 | } 97 | 98 | return Double.compare(ls.y2, y2); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/pgdatatypes/Circle.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.pgdatatypes; 2 | 3 | import java.util.Objects; 4 | 5 | public class Circle implements Comparable { 6 | private double mx; 7 | private double my; 8 | private double radius; 9 | 10 | /** 11 | * Describes a circle in a 2-d plane. 12 | * 13 | * @param x x coordinate of middle 14 | * @param y y coordinate of middle 15 | * @param radius radius of circle 16 | */ 17 | public Circle(double x, double y, double radius) { 18 | this.mx = x; 19 | this.my = y; 20 | this.radius = radius; 21 | } 22 | 23 | public double getX() { 24 | return mx; 25 | } 26 | 27 | public void setX(double x) { 28 | this.mx = x; 29 | } 30 | 31 | public double getY() { 32 | return my; 33 | } 34 | 35 | public void setY(double y) { 36 | this.my = y; 37 | } 38 | 39 | public double getRadius() { 40 | return radius; 41 | } 42 | 43 | public void setRadius(double radius) { 44 | this.radius = radius; 45 | } 46 | 47 | @Override 48 | public boolean equals(Object o) { 49 | if (this == o) { 50 | return true; 51 | } 52 | if (o == null || getClass() != o.getClass()) { 53 | return false; 54 | } 55 | Circle circle = (Circle) o; 56 | return Double.compare(circle.mx, mx) == 0 57 | && Double.compare(circle.my, my) == 0 58 | && Double.compare(circle.radius, radius) == 0; 59 | } 60 | 61 | @Override 62 | public int hashCode() { 63 | return Objects.hash(mx, my, radius); 64 | } 65 | 66 | @Override 67 | public int compareTo(Circle circle) { 68 | int c = Double.compare(circle.mx, mx); 69 | 70 | if (c != 0) { 71 | return c; 72 | } 73 | 74 | c = Double.compare(circle.my, my); 75 | 76 | if (c != 0) { 77 | return c; 78 | } 79 | 80 | return Double.compare(circle.radius, radius); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/pgdatatypes/Line.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.pgdatatypes; 2 | 3 | import java.util.Objects; 4 | 5 | public class Line implements Comparable { 6 | private double ma; 7 | private double mb; 8 | private double mc; 9 | 10 | /** 11 | * An infinite line on a plane, represented by Ax + By + C. 12 | * 13 | * @param a x axis 14 | * @param b y axis 15 | * @param c constant 16 | */ 17 | public Line(double a, double b, double c) { 18 | this.ma = a; 19 | this.mb = b; 20 | this.mc = c; 21 | } 22 | 23 | public double getA() { 24 | return ma; 25 | } 26 | 27 | public void setA(double a) { 28 | this.ma = a; 29 | } 30 | 31 | public double getB() { 32 | return mb; 33 | } 34 | 35 | public void setB(double b) { 36 | this.mb = b; 37 | } 38 | 39 | public double getC() { 40 | return mc; 41 | } 42 | 43 | public void setC(double c) { 44 | this.mc = c; 45 | } 46 | 47 | @Override 48 | public boolean equals(Object o) { 49 | if (this == o) { 50 | return true; 51 | } 52 | if (o == null || getClass() != o.getClass()) { 53 | return false; 54 | } 55 | Line line = (Line) o; 56 | return Double.compare(line.ma, ma) == 0 57 | && Double.compare(line.mb, mb) == 0 58 | && Double.compare(line.mc, mc) == 0; 59 | } 60 | 61 | @Override 62 | public int hashCode() { 63 | return Objects.hash(ma, mb, mc); 64 | } 65 | 66 | @Override 67 | public int compareTo(Line line) { 68 | int c = Double.compare(line.ma, ma); 69 | 70 | if (c != 0) { 71 | return c; 72 | } 73 | 74 | c = Double.compare(line.mb, mb); 75 | 76 | if (c != 0) { 77 | return c; 78 | } 79 | 80 | return Double.compare(line.mc, mc); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/pgdatatypes/LineSegment.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.pgdatatypes; 2 | 3 | import java.util.Objects; 4 | 5 | public class LineSegment implements Comparable { 6 | private double x1; 7 | private double y1; 8 | private double x2; 9 | private double y2; 10 | 11 | /** 12 | * Represent a line segment between two points. 13 | * 14 | * @param x1 first point x 15 | * @param y1 first point y 16 | * @param x2 second point x 17 | * @param y2 second point y 18 | */ 19 | public LineSegment(double x1, double y1, double x2, double y2) { 20 | this.x1 = x1; 21 | this.y1 = y1; 22 | this.x2 = x2; 23 | this.y2 = y2; 24 | } 25 | 26 | public double getX1() { 27 | return x1; 28 | } 29 | 30 | public void setX1(double x1) { 31 | this.x1 = x1; 32 | } 33 | 34 | public double getY1() { 35 | return y1; 36 | } 37 | 38 | public void setY1(double y1) { 39 | this.y1 = y1; 40 | } 41 | 42 | public double getX2() { 43 | return x2; 44 | } 45 | 46 | public void setX2(double x2) { 47 | this.x2 = x2; 48 | } 49 | 50 | public double getY2() { 51 | return y2; 52 | } 53 | 54 | public void setY2(double y2) { 55 | this.y2 = y2; 56 | } 57 | 58 | @Override 59 | public boolean equals(Object o) { 60 | if (this == o) { 61 | return true; 62 | } 63 | if (o == null || getClass() != o.getClass()) { 64 | return false; 65 | } 66 | LineSegment that = (LineSegment) o; 67 | return Double.compare(that.x1, x1) == 0 68 | && Double.compare(that.y1, y1) == 0 69 | && Double.compare(that.x2, x2) == 0 70 | && Double.compare(that.y2, y2) == 0; 71 | } 72 | 73 | @Override 74 | public int hashCode() { 75 | return Objects.hash(x1, y1, x2, y2); 76 | } 77 | 78 | @Override 79 | public int compareTo(LineSegment ls) { 80 | int c = Double.compare(ls.x1, x1); 81 | 82 | if (c != 0) { 83 | return c; 84 | } 85 | 86 | c = Double.compare(ls.y1, y1); 87 | 88 | if (c != 0) { 89 | return c; 90 | } 91 | 92 | c = Double.compare(ls.x2, x2); 93 | 94 | if (c != 0) { 95 | return c; 96 | } 97 | 98 | return Double.compare(ls.y2, y2); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/pgdatatypes/Path.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.pgdatatypes; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | import java.util.Objects; 7 | 8 | public class Path implements Comparable { 9 | private List points; 10 | private boolean closed; 11 | 12 | /** 13 | * Initializes the Path from a list of points. 14 | * 15 | * @param closed if the Path is closed in a circle or open 16 | * @param points not allowed to be null 17 | */ 18 | public Path(boolean closed, List points) { 19 | if (points == null) { 20 | throw new RuntimeException("point list not allowed to be null"); 21 | } 22 | this.closed = closed; 23 | this.points = points; 24 | } 25 | 26 | /** 27 | * Initializes the Path from a list of points. 28 | * 29 | * @param closed if the Path is closed in a circle or open 30 | * @param points not allowed to be null 31 | */ 32 | public Path(boolean closed, Point... points) { 33 | if (points == null) { 34 | throw new RuntimeException("point list not allowed to be null"); 35 | } 36 | this.closed = closed; 37 | this.points = new ArrayList<>(); 38 | this.points.addAll(Arrays.asList(points)); 39 | } 40 | 41 | public List getPoints() { 42 | return points; 43 | } 44 | 45 | /** 46 | * Sets the points that this Path consists of. 47 | * 48 | * @param points not allowed to be null 49 | */ 50 | public void setPoints(List points) { 51 | if (points == null) { 52 | throw new RuntimeException("point list not allowed to be null"); 53 | } 54 | this.points = points; 55 | } 56 | 57 | public boolean isClosed() { 58 | return closed; 59 | } 60 | 61 | public void setClosed(boolean closed) { 62 | this.closed = closed; 63 | } 64 | 65 | @Override 66 | public boolean equals(Object o) { 67 | if (this == o) { 68 | return true; 69 | } 70 | if (o == null || getClass() != o.getClass()) { 71 | return false; 72 | } 73 | Path path = (Path) o; 74 | return closed == path.closed 75 | && Objects.equals(points, path.points); 76 | } 77 | 78 | @Override 79 | public int hashCode() { 80 | return Objects.hash(points, closed); 81 | } 82 | 83 | @Override 84 | public int compareTo(Path p) { 85 | int c = Integer.compare(p.points.size(), points.size()); 86 | 87 | if (c != 0) { 88 | return c; 89 | } 90 | 91 | c = Boolean.compare(p.closed, closed); 92 | 93 | if (c != 0) { 94 | return c; 95 | } 96 | 97 | for (int i = 0; i < points.size(); i++) { 98 | c = p.points.get(i).compareTo(points.get(i)); 99 | 100 | if (c != 0) { 101 | return c; 102 | } 103 | } 104 | return 0; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/pgdatatypes/Point.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.pgdatatypes; 2 | 3 | import java.util.Objects; 4 | 5 | public class Point implements Comparable { 6 | private double mx; 7 | private double my; 8 | 9 | public Point(double x, double y) { 10 | this.mx = x; 11 | this.my = y; 12 | } 13 | 14 | public double getX() { 15 | return mx; 16 | } 17 | 18 | public void setX(double x) { 19 | this.mx = x; 20 | } 21 | 22 | public double getY() { 23 | return my; 24 | } 25 | 26 | public void setY(double y) { 27 | this.my = y; 28 | } 29 | 30 | @Override 31 | public boolean equals(Object o) { 32 | if (this == o) { 33 | return true; 34 | } 35 | if (o == null || getClass() != o.getClass()) { 36 | return false; 37 | } 38 | Point point = (Point) o; 39 | return Double.compare(point.mx, mx) == 0 40 | && Double.compare(point.my, my) == 0; 41 | } 42 | 43 | @Override 44 | public int hashCode() { 45 | return Objects.hash(mx, my); 46 | } 47 | 48 | @Override 49 | public int compareTo(Point p2) { 50 | int c = Double.compare(mx, p2.mx); 51 | 52 | if (c != 0) { 53 | return c; 54 | } 55 | 56 | return Double.compare(my, p2.my); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/pgdatatypes/Polygon.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.pgdatatypes; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | import java.util.Objects; 7 | 8 | public class Polygon implements Comparable { 9 | private List points; 10 | 11 | /** 12 | * Initializes the Polygon from a list of points. 13 | * 14 | * @param points not allowed to be null 15 | */ 16 | public Polygon(List points) { 17 | if (points == null) { 18 | throw new RuntimeException("point list not allowed to be null"); 19 | } 20 | this.points = points; 21 | } 22 | 23 | /** 24 | * Initializes the Polygon from a list of points. 25 | * 26 | * @param points not allowed to be null 27 | */ 28 | public Polygon(Point... points) { 29 | if (points == null) { 30 | throw new RuntimeException("point list not allowed to be null"); 31 | } 32 | this.points = new ArrayList<>(); 33 | this.points.addAll(Arrays.asList(points)); 34 | } 35 | 36 | public List getPoints() { 37 | return points; 38 | } 39 | 40 | /** 41 | * Sets the points that this Path consists of. 42 | * 43 | * @param points not allowed to be null 44 | */ 45 | public void setPoints(List points) { 46 | if (points == null) { 47 | throw new RuntimeException("point list not allowed to be null"); 48 | } 49 | this.points = points; 50 | } 51 | 52 | @Override 53 | public boolean equals(Object o) { 54 | if (this == o) { 55 | return true; 56 | } 57 | if (o == null || getClass() != o.getClass()) { 58 | return false; 59 | } 60 | Polygon polygon = (Polygon) o; 61 | return Objects.equals(points, polygon.points); 62 | } 63 | 64 | @Override 65 | public int hashCode() { 66 | return Objects.hash(points); 67 | } 68 | 69 | @Override 70 | public int compareTo(Polygon p) { 71 | int c = Integer.compare(p.points.size(), points.size()); 72 | 73 | if (c != 0) { 74 | return c; 75 | } 76 | 77 | for (int i = 0; i < points.size(); i++) { 78 | c = p.points.get(i).compareTo(points.get(i)); 79 | 80 | if (c != 0) { 81 | return c; 82 | } 83 | } 84 | return 0; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/submissions/CloseSubmission.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.submissions; 2 | 3 | import java.util.List; 4 | import java.util.concurrent.CompletableFuture; 5 | import java.util.concurrent.CompletionStage; 6 | import java.util.concurrent.ExecutionException; 7 | import java.util.concurrent.atomic.AtomicBoolean; 8 | import java.util.function.Consumer; 9 | import java.util.function.Supplier; 10 | import java.util.stream.Collector; 11 | import org.postgresql.adba.PgSubmission; 12 | import org.postgresql.adba.communication.packets.DataRow; 13 | import org.postgresql.adba.operations.helpers.ParameterHolder; 14 | 15 | public class CloseSubmission implements PgSubmission { 16 | private final Supplier cancel; 17 | private CompletableFuture publicStage; 18 | private final AtomicBoolean sendConsumed = new AtomicBoolean(false); 19 | 20 | private Collector collector; 21 | private Object collectorHolder; 22 | private Consumer errorHandler; 23 | 24 | public CloseSubmission(Supplier cancel, Consumer errorHandler) { 25 | this.cancel = cancel; 26 | this.errorHandler = errorHandler; 27 | } 28 | 29 | @Override 30 | public CompletionStage cancel() { 31 | return new CompletableFuture().completeAsync(cancel); 32 | } 33 | 34 | @Override 35 | public CompletionStage getCompletionStage() { 36 | if (publicStage == null) { 37 | publicStage = new CompletableFuture<>(); 38 | } 39 | 40 | return publicStage; 41 | } 42 | 43 | @Override 44 | public String getSql() { 45 | return null; 46 | } 47 | 48 | @Override 49 | public AtomicBoolean getSendConsumed() { 50 | return sendConsumed; 51 | } 52 | 53 | @Override 54 | public ParameterHolder getHolder() { 55 | return null; 56 | } 57 | 58 | @Override 59 | public Types getCompletionType() { 60 | return BaseSubmission.Types.CLOSE; 61 | } 62 | 63 | @Override 64 | public void setCollector(Collector collector) { 65 | this.collector = collector; 66 | 67 | collectorHolder = collector.supplier().get(); 68 | } 69 | 70 | @Override 71 | public Object finish(Object socketChannel) { 72 | return null; 73 | } 74 | 75 | @Override 76 | public void addRow(DataRow row) { 77 | try { 78 | collector.accumulator().accept(collectorHolder, row); 79 | } catch (Throwable e) { 80 | publicStage.completeExceptionally(e); 81 | } 82 | } 83 | 84 | @Override 85 | public List getParamTypes() throws ExecutionException, InterruptedException { 86 | return null; 87 | } 88 | 89 | @Override 90 | public int numberOfQueryRepetitions() throws ExecutionException, InterruptedException { 91 | return 1; 92 | } 93 | 94 | @Override 95 | public Consumer getErrorHandler() { 96 | return errorHandler; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/util/PgCount.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.util; 2 | 3 | import jdk.incubator.sql2.Result; 4 | 5 | import java.util.Objects; 6 | 7 | public class PgCount implements Result.RowCount { 8 | private long count; 9 | 10 | public PgCount(long count) { 11 | this.count = count; 12 | } 13 | 14 | @Override 15 | public long getCount() { 16 | return count; 17 | } 18 | 19 | @Override 20 | public boolean equals(Object o) { 21 | if (this == o) { 22 | return true; 23 | } 24 | 25 | if (o == null || getClass() != o.getClass()) { 26 | return false; 27 | } 28 | 29 | PgCount pgCount = (PgCount) o; 30 | return count == pgCount.count; 31 | } 32 | 33 | @Override 34 | public int hashCode() { 35 | return Objects.hash(count); 36 | } 37 | 38 | @Override 39 | public String toString() { 40 | return "" + count; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/util/QuadFunction.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.util; 2 | 3 | import java.util.Objects; 4 | import java.util.function.Function; 5 | 6 | @FunctionalInterface 7 | public interface QuadFunction { 8 | 9 | R apply(A a, B b, C c, D d); 10 | 11 | default QuadFunction andThen( 12 | Function after) { 13 | Objects.requireNonNull(after); 14 | return (A a, B b, C c, D d) -> after.apply(apply(a, b, c, d)); 15 | } 16 | } -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/util/scram/common/ScramAttributeValue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, OnGres. 3 | * 4 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 5 | * following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following 8 | * disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the 11 | * following disclaimer in the documentation and/or other materials provided with the distribution. 12 | * 13 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 14 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 15 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 16 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 17 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 18 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 19 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | * 21 | */ 22 | 23 | 24 | package org.postgresql.adba.util.scram.common; 25 | 26 | 27 | import static org.postgresql.adba.util.scram.common.util.Preconditions.checkNotNull; 28 | 29 | import org.postgresql.adba.util.scram.common.exception.ScramParseException; 30 | import org.postgresql.adba.util.scram.common.util.AbstractCharAttributeValue; 31 | 32 | 33 | /** 34 | * Parse and write SCRAM Attribute-Value pairs. 35 | */ 36 | public class ScramAttributeValue extends AbstractCharAttributeValue { 37 | 38 | public ScramAttributeValue(ScramAttributes attribute, String value) { 39 | super(attribute, checkNotNull(value, "value")); 40 | } 41 | 42 | public static StringBuffer writeTo(StringBuffer sb, ScramAttributes attribute, String value) { 43 | return new ScramAttributeValue(attribute, value).writeTo(sb); 44 | } 45 | 46 | /** 47 | * Parses a potential ScramAttributeValue String. 48 | * 49 | * @param value The string that contains the Attribute-Value pair. 50 | * @return The parsed class 51 | * @throws ScramParseException If the argument is empty or an invalid Attribute-Value 52 | */ 53 | public static ScramAttributeValue parse(String value) 54 | throws ScramParseException { 55 | if (null == value || value.length() < 3 || value.charAt(1) != '=') { 56 | throw new ScramParseException("Invalid ScramAttributeValue '" + value + "'"); 57 | } 58 | 59 | return new ScramAttributeValue(ScramAttributes.byChar(value.charAt(0)), value.substring(2)); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/util/scram/common/exception/ScramException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, OnGres. 3 | * 4 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 5 | * following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following 8 | * disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the 11 | * following disclaimer in the documentation and/or other materials provided with the distribution. 12 | * 13 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 14 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 15 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 16 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 17 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 18 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 19 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | * 21 | */ 22 | 23 | 24 | package org.postgresql.adba.util.scram.common.exception; 25 | 26 | 27 | import javax.security.sasl.SaslException; 28 | 29 | 30 | /** 31 | * This class represents an error when using SCRAM, which is a SASL method. 32 | * 33 | * {@link SaslException} 34 | */ 35 | public class ScramException extends SaslException { 36 | 37 | /** 38 | * Constructs a new instance of ScramException with a detailed message. 39 | * 40 | * @param detail A String containing details about the exception 41 | */ 42 | public ScramException(String detail) { 43 | super(detail); 44 | } 45 | 46 | /** 47 | * Constructs a new instance of ScramException with a detailed message and a root cause. 48 | * 49 | * @param detail A String containing details about the exception 50 | * @param ex The root exception 51 | */ 52 | public ScramException(String detail, Throwable ex) { 53 | super(detail, ex); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/util/scram/common/exception/ScramInvalidServerSignatureException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, OnGres. 3 | * 4 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 5 | * following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following 8 | * disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the 11 | * following disclaimer in the documentation and/or other materials provided with the distribution. 12 | * 13 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 14 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 15 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 16 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 17 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 18 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 19 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | * 21 | */ 22 | 23 | 24 | package org.postgresql.adba.util.scram.common.exception; 25 | 26 | 27 | /** 28 | * This class represents an error when parsing SCRAM messages. 29 | */ 30 | public class ScramInvalidServerSignatureException extends ScramException { 31 | 32 | /** 33 | * Constructs a new instance of ScramInvalidServerSignatureException with a detailed message. 34 | * 35 | * @param detail A String containing details about the exception 36 | */ 37 | public ScramInvalidServerSignatureException(String detail) { 38 | super(detail); 39 | } 40 | 41 | /** 42 | * Constructs a new instance of ScramInvalidServerSignatureException with a detailed message and a root cause. 43 | * 44 | * @param detail A String containing details about the exception 45 | * @param ex The root exception 46 | */ 47 | public ScramInvalidServerSignatureException(String detail, Throwable ex) { 48 | super(detail, ex); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/util/scram/common/exception/ScramParseException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, OnGres. 3 | * 4 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 5 | * following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following 8 | * disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the 11 | * following disclaimer in the documentation and/or other materials provided with the distribution. 12 | * 13 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 14 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 15 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 16 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 17 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 18 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 19 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | * 21 | */ 22 | 23 | 24 | package org.postgresql.adba.util.scram.common.exception; 25 | 26 | 27 | /** 28 | * This class represents an error when parsing SCRAM messages. 29 | */ 30 | public class ScramParseException extends ScramException { 31 | 32 | /** 33 | * Constructs a new instance of ScramParseException with a detailed message. 34 | * 35 | * @param detail A String containing details about the exception 36 | */ 37 | public ScramParseException(String detail) { 38 | super(detail); 39 | } 40 | 41 | /** 42 | * Constructs a new instance of ScramParseException with a detailed message and a root cause. 43 | * 44 | * @param detail A String containing details about the exception 45 | * @param ex The root exception 46 | */ 47 | public ScramParseException(String detail, Throwable ex) { 48 | super(detail, ex); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/util/scram/common/exception/ScramServerErrorException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, OnGres. 3 | * 4 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 5 | * following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following 8 | * disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the 11 | * following disclaimer in the documentation and/or other materials provided with the distribution. 12 | * 13 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 14 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 15 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 16 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 17 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 18 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 19 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | * 21 | */ 22 | 23 | 24 | package org.postgresql.adba.util.scram.common.exception; 25 | 26 | 27 | import org.postgresql.adba.util.scram.common.message.ServerFinalMessage; 28 | 29 | 30 | /** 31 | * This class represents an error when parsing SCRAM messages. 32 | */ 33 | public class ScramServerErrorException extends ScramException { 34 | 35 | private final ServerFinalMessage.Error error; 36 | 37 | private static String toString(ServerFinalMessage.Error error) { 38 | return "Server-final-message is an error message. Error: " + error.getErrorMessage(); 39 | } 40 | 41 | /** 42 | * Constructs a new instance of ScramServerErrorException with a detailed message. 43 | * 44 | * @param error The SCRAM error in the message 45 | */ 46 | public ScramServerErrorException(ServerFinalMessage.Error error) { 47 | super(toString(error)); 48 | this.error = error; 49 | } 50 | 51 | /** 52 | * Constructs a new instance of ScramServerErrorException with a detailed message and a root cause. 53 | * 54 | * @param error The SCRAM error in the message 55 | * @param ex The root exception 56 | */ 57 | public ScramServerErrorException(ServerFinalMessage.Error error, Throwable ex) { 58 | super(toString(error), ex); 59 | this.error = error; 60 | } 61 | 62 | public ServerFinalMessage.Error getError() { 63 | return error; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/util/scram/common/gssapi/Gs2AttributeValue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, OnGres. 3 | * 4 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 5 | * following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following 8 | * disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the 11 | * following disclaimer in the documentation and/or other materials provided with the distribution. 12 | * 13 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 14 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 15 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 16 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 17 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 18 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 19 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | * 21 | */ 22 | 23 | 24 | package org.postgresql.adba.util.scram.common.gssapi; 25 | 26 | 27 | import org.postgresql.adba.util.scram.common.util.AbstractCharAttributeValue; 28 | 29 | /** 30 | * Parse and write GS2 Attribute-Value pairs. 31 | */ 32 | public class Gs2AttributeValue extends AbstractCharAttributeValue { 33 | 34 | public Gs2AttributeValue(Gs2Attributes attribute, String value) { 35 | super(attribute, value); 36 | } 37 | 38 | public static StringBuffer writeTo(StringBuffer sb, Gs2Attributes attribute, String value) { 39 | return new Gs2AttributeValue(attribute, value).writeTo(sb); 40 | } 41 | 42 | /** 43 | * Parses a potential Gs2AttributeValue String. 44 | * 45 | * @param value The string that contains the Attribute-Value pair (where value is optional). 46 | * @return The parsed class, or null if the String was null. 47 | * @throws IllegalArgumentException If the String is an invalid Gs2AttributeValue 48 | */ 49 | public static Gs2AttributeValue parse(String value) throws IllegalArgumentException { 50 | if (null == value) { 51 | return null; 52 | } 53 | 54 | if (value.length() < 1 || value.length() == 2 || (value.length() > 2 && value.charAt(1) != '=')) { 55 | throw new IllegalArgumentException("Invalid Gs2AttributeValue"); 56 | } 57 | 58 | return new Gs2AttributeValue( 59 | Gs2Attributes.byChar(value.charAt(0)), 60 | value.length() > 2 ? value.substring(2) : null 61 | ); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/util/scram/common/stringprep/StringPreparation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, OnGres. 3 | * 4 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 5 | * following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following 8 | * disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the 11 | * following disclaimer in the documentation and/or other materials provided with the distribution. 12 | * 13 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 14 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 15 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 16 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 17 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 18 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 19 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | * 21 | */ 22 | 23 | 24 | package org.postgresql.adba.util.scram.common.stringprep; 25 | 26 | 27 | /** 28 | * Interface for all possible String Preparations mechanisms. 29 | */ 30 | public interface StringPreparation { 31 | 32 | /** 33 | * Normalize a UTF-8 String according to this String Preparation rules. 34 | * 35 | * @param value The String to prepare 36 | * @return The prepared String 37 | * @throws IllegalArgumentException If the String to prepare is not valid. 38 | */ 39 | String normalize(String value) throws IllegalArgumentException; 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/util/scram/common/util/AbstractStringWritable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, OnGres. 3 | * 4 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 5 | * following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following 8 | * disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the 11 | * following disclaimer in the documentation and/or other materials provided with the distribution. 12 | * 13 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 14 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 15 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 16 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 17 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 18 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 19 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | * 21 | */ 22 | 23 | 24 | package org.postgresql.adba.util.scram.common.util; 25 | 26 | 27 | /** 28 | * Basic implementation of the StringWritable interface, that overrides the toString() method. 29 | */ 30 | public abstract class AbstractStringWritable implements StringWritable { 31 | 32 | public String toString() { 33 | return writeTo(new StringBuffer()).toString(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/util/scram/common/util/CharAttribute.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, OnGres. 3 | * 4 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 5 | * following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following 8 | * disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the 11 | * following disclaimer in the documentation and/or other materials provided with the distribution. 12 | * 13 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 14 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 15 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 16 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 17 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 18 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 19 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | * 21 | */ 22 | 23 | 24 | package org.postgresql.adba.util.scram.common.util; 25 | 26 | 27 | /** 28 | * Represents an attribute (a key name) that is represented by a single char. 29 | */ 30 | public interface CharAttribute { 31 | 32 | /** 33 | * Return the char used to represent this attribute. 34 | * 35 | * @return The character of the attribute 36 | */ 37 | char getChar(); 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/util/scram/common/util/CharAttributeValue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, OnGres. 3 | * 4 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 5 | * following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following 8 | * disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the 11 | * following disclaimer in the documentation and/or other materials provided with the distribution. 12 | * 13 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 14 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 15 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 16 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 17 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 18 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 19 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | * 21 | */ 22 | 23 | 24 | package org.postgresql.adba.util.scram.common.util; 25 | 26 | 27 | /** 28 | * Augments a {@link CharAttribute} with a String value and the method(s) to write its data to a StringBuffer. 29 | */ 30 | public interface CharAttributeValue extends CharAttribute, StringWritable { 31 | 32 | /** 33 | * Returns the value associated with the {@link CharAttribute}. 34 | * 35 | * @return The String value or null if no value is associated 36 | */ 37 | String getValue(); 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/util/scram/common/util/StringWritable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, OnGres. 3 | * 4 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 5 | * following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following 8 | * disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the 11 | * following disclaimer in the documentation and/or other materials provided with the distribution. 12 | * 13 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 14 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 15 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 16 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 17 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 18 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 19 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | * 21 | */ 22 | 23 | 24 | package org.postgresql.adba.util.scram.common.util; 25 | 26 | 27 | /** 28 | * Interface to denote classes which can write to a StringBuffer. 29 | */ 30 | public interface StringWritable { 31 | 32 | /** 33 | * Write the class information to the given StringBuffer. 34 | * 35 | * @param sb Where to write the data. 36 | * @return The same StringBuffer. 37 | */ 38 | StringBuffer writeTo(StringBuffer sb); 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/util/scram/common/util/UsAsciiUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, OnGres. 3 | * 4 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 5 | * following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following 8 | * disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the 11 | * following disclaimer in the documentation and/or other materials provided with the distribution. 12 | * 13 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 14 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 15 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 16 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 17 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 18 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 19 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | * 21 | */ 22 | 23 | 24 | package org.postgresql.adba.util.scram.common.util; 25 | 26 | 27 | import static org.postgresql.adba.util.scram.common.util.Preconditions.checkNotNull; 28 | 29 | 30 | public class UsAsciiUtils { 31 | 32 | /** 33 | * Removes non-printable characters from the US-ASCII String. 34 | * 35 | * @param value The original String 36 | * @return The possibly modified String, without non-printable US-ASCII characters. 37 | * @throws IllegalArgumentException If the String is null or contains non US-ASCII characters. 38 | */ 39 | public static String toPrintable(String value) throws IllegalArgumentException { 40 | checkNotNull(value, "value"); 41 | 42 | char[] printable = new char[value.length()]; 43 | int i = 0; 44 | for (char chr : value.toCharArray()) { 45 | int c = (int) chr; 46 | if (c < 0 || c >= 127) { 47 | throw new IllegalArgumentException("value contains character '" + chr + "' which is non US-ASCII"); 48 | } else if (c > 32) { 49 | printable[i++] = chr; 50 | } 51 | } 52 | 53 | return i == value.length() ? value : new String(printable, 0, i); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/util/tlschannel/BufferAllocator.java: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License 3 | 4 | Copyright (c) [2015-2018] all contributors of https://github.com/marianobarrios/tls-channel, Alexander Kjäll 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | package org.postgresql.adba.util.tlschannel; 26 | 27 | import java.nio.ByteBuffer; 28 | 29 | /** 30 | * A factory for {@link ByteBuffer}s. Implementations are free to return heap or direct buffers, or to do any kind of pooling. 31 | * They are also expected to be thread-safe. 32 | */ 33 | public interface BufferAllocator { 34 | 35 | /** 36 | * Allocate a {@link ByteBuffer} with the given initial capacity. 37 | * @param size initial size of buffer 38 | * @return a ByteBuffer of the specified size 39 | */ 40 | ByteBuffer allocate(int size); 41 | 42 | /** 43 | * Deallocate the given {@link ByteBuffer}. 44 | * 45 | * @param buffer the buffer to deallocate, that should have been allocated using the same {@link BufferAllocator} instance 46 | */ 47 | void free(ByteBuffer buffer); 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/util/tlschannel/HeapBufferAllocator.java: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License 3 | 4 | Copyright (c) [2015-2018] all contributors of https://github.com/marianobarrios/tls-channel, Alexander Kjäll 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | package org.postgresql.adba.util.tlschannel; 26 | 27 | import java.nio.ByteBuffer; 28 | 29 | /** 30 | * Allocator that creates heap buffers. The {@link #free(ByteBuffer)} method is a no-op, as heap buffers are handled completely by 31 | * the garbage collector. 32 | * 33 | *

Direct buffers are generally used as a simple and generally good enough default solution.

34 | */ 35 | public class HeapBufferAllocator implements BufferAllocator { 36 | 37 | @Override 38 | public ByteBuffer allocate(int size) { 39 | return ByteBuffer.allocate(size); 40 | } 41 | 42 | @Override 43 | public void free(ByteBuffer buffer) { 44 | // GC does it 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/util/tlschannel/NeedsReadException.java: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License 3 | 4 | Copyright (c) [2015-2018] all contributors of https://github.com/marianobarrios/tls-channel, Alexander Kjäll 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | package org.postgresql.adba.util.tlschannel; 26 | 27 | import java.nio.channels.ByteChannel; 28 | import java.nio.channels.Selector; 29 | import java.nio.channels.SocketChannel; 30 | 31 | /** 32 | * This exception signals the caller that the operation cannot continue because bytesProduced need to be read from the underlying 33 | * {@link ByteChannel}, the channel is non-blocking and there are no bytesProduced available. The caller should try the operation 34 | * again, either with the channel in blocking mode of after ensuring that bytesProduced are ready. 35 | * 36 | *

For {@link SocketChannel}s, a {@link Selector} can be used to find out when the method should be retried.

37 | * 38 | *

Caveat: Any {@link TlsChannel} I/O method can throw this exception. In particular, write may want to read data. 39 | * This is because TLS handshakes may occur at any time (initiated by either the client or the server).

40 | * 41 | *

This exception is akin to the SSL_ERROR_WANT_READ error code used by OpenSSL.

42 | * 43 | * @see 44 | * OpenSSL error documentation 45 | */ 46 | public class NeedsReadException extends WouldBlockException { 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/util/tlschannel/NeedsTaskException.java: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License 3 | 4 | Copyright (c) [2015-2018] all contributors of https://github.com/marianobarrios/tls-channel, Alexander Kjäll 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | package org.postgresql.adba.util.tlschannel; 26 | 27 | /** 28 | * This exception signals the caller that the operation could not continue because a CPU-intensive operation (typically a TLS 29 | * handshaking) needs to be executed and the {@link TlsChannel} is configured to not run tasks. This allows the application to run 30 | * these tasks in some other threads, in order to not slow the selection loop. The method that threw the exception should be 31 | * retried once the task supplied by {@link #getTask()} is executed and finished. 32 | * 33 | *

This exception is akin to the SSL_ERROR_WANT_ASYNC error code used by OpenSSL (but note that in OpenSSL, the task is 34 | * executed by the library, while with the {@link TlsChannel}, the calling code is responsible for the execution).

35 | * 36 | * @see 37 | * OpenSSL error documentation 38 | */ 39 | public class NeedsTaskException extends TlsChannelFlowControlException { 40 | 41 | private Runnable task; 42 | 43 | public NeedsTaskException(Runnable task) { 44 | this.task = task; 45 | } 46 | 47 | public Runnable getTask() { 48 | return task; 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/util/tlschannel/NeedsWriteException.java: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License 3 | 4 | Copyright (c) [2015-2018] all contributors of https://github.com/marianobarrios/tls-channel, Alexander Kjäll 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | package org.postgresql.adba.util.tlschannel; 26 | 27 | import java.nio.channels.ByteChannel; 28 | import java.nio.channels.Selector; 29 | import java.nio.channels.SocketChannel; 30 | 31 | /** 32 | * This exception signals the caller that the operation cannot continue because bytesProduced need to be write to the underlying 33 | * {@link ByteChannel}, the channel is non-blocking and there are no buffer space available. The caller should try the operation 34 | * again, either with the channel in blocking mode of after ensuring that buffer space exists. 35 | * 36 | *

For {@link SocketChannel}s, a {@link Selector} can be used to find out when the method should be retried.

37 | * 38 | *

Caveat: Any {@link TlsChannel} I/O method can throw this exception. In particular, read may want to write data. 39 | * This is because TLS handshakes may occur at any time (initiated by either the client or the server).

40 | * 41 | *

This exception is akin to the SSL_ERROR_WANT_WRITE error code used by OpenSSL.

42 | * 43 | * @see 44 | * OpenSSL error documentation 45 | */ 46 | 47 | public class NeedsWriteException extends WouldBlockException { 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/util/tlschannel/TlsChannelFlowControlException.java: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License 3 | 4 | Copyright (c) [2015-2018] all contributors of https://github.com/marianobarrios/tls-channel, Alexander Kjäll 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | package org.postgresql.adba.util.tlschannel; 26 | 27 | import java.io.IOException; 28 | import java.nio.channels.ByteChannel; 29 | 30 | /** 31 | * Base class for exceptions used to control flow. 32 | * 33 | *

Because exceptions of this class are not used to signal errors, they don't contain stack traces, to improve efficiency.

34 | * 35 | *

This class inherits from {@link IOException} as a compromise to allow {@link TlsChannel} to throw it while still 36 | * implementing the {@link ByteChannel} interface.

37 | */ 38 | public abstract class TlsChannelFlowControlException extends IOException { 39 | 40 | public TlsChannelFlowControlException() { 41 | super(); 42 | } 43 | 44 | /** 45 | * For efficiency, override this method to do nothing. 46 | */ 47 | @Override 48 | public Throwable fillInStackTrace() { 49 | return this; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/util/tlschannel/WouldBlockException.java: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License 3 | 4 | Copyright (c) [2015-2018] all contributors of https://github.com/marianobarrios/tls-channel, Alexander Kjäll 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | package org.postgresql.adba.util.tlschannel; 26 | 27 | /** 28 | * Signals that some IO operation cannot continue because the channel is in non blocking mode and some blocking would otherwise 29 | * happen. 30 | */ 31 | public class WouldBlockException extends TlsChannelFlowControlException { 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/util/tlschannel/impl/ByteBufferUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License 3 | 4 | Copyright (c) [2015-2018] all contributors of https://github.com/marianobarrios/tls-channel, Alexander Kjäll 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | package org.postgresql.adba.util.tlschannel.impl; 26 | 27 | import java.nio.ByteBuffer; 28 | 29 | public class ByteBufferUtil { 30 | 31 | /** 32 | * copies bytebuffers. 33 | * @param src source 34 | * @param dst destination 35 | * @param length bytes to copy 36 | */ 37 | public static void copy(ByteBuffer src, ByteBuffer dst, int length) { 38 | if (length < 0) { 39 | throw new IllegalArgumentException("negative length"); 40 | } 41 | if (src.remaining() < length) { 42 | throw new IllegalArgumentException( 43 | String.format("source buffer does not have enough remaining capacity (%d < %d)", src.remaining(), length)); 44 | } 45 | if (dst.remaining() < length) { 46 | throw new IllegalArgumentException( 47 | String.format("destination buffer does not have enough remaining capacity (%d < %d)", dst.remaining(), length)); 48 | } 49 | if (length == 0) { 50 | return; 51 | } 52 | ByteBuffer tmp = src.duplicate(); 53 | tmp.limit(src.position() + length); 54 | dst.put(tmp); 55 | src.position(src.position() + length); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/util/tlschannel/util/TlsChannelCallbackException.java: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License 3 | 4 | Copyright (c) [2015-2018] all contributors of https://github.com/marianobarrios/tls-channel, Alexander Kjäll 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | package org.postgresql.adba.util.tlschannel.util; 26 | 27 | import javax.net.ssl.SSLException; 28 | import org.postgresql.adba.util.tlschannel.TlsChannel; 29 | 30 | /** 31 | * Thrown during {@link TlsChannel} handshake to indicate that a user-supplied function threw an exception. 32 | */ 33 | public class TlsChannelCallbackException extends SSLException { 34 | 35 | public TlsChannelCallbackException(String message, Throwable throwable) { 36 | super(message, throwable); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/org/postgresql/adba/util/tlschannel/util/Util.java: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License 3 | 4 | Copyright (c) [2015-2018] all contributors of https://github.com/marianobarrios/tls-channel, Alexander Kjäll 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | package org.postgresql.adba.util.tlschannel.util; 26 | 27 | import javax.net.ssl.SSLEngineResult; 28 | 29 | public class Util { 30 | /** 31 | * throws if false. 32 | * @param condition to throw or not 33 | */ 34 | public static void assertTrue(boolean condition) { 35 | if (!condition) { 36 | throw new AssertionError(); 37 | } 38 | } 39 | 40 | /** 41 | * Convert a {@link SSLEngineResult} into a {@link String}, this is needed because the supplied method includes a log-breaking 42 | * newline. 43 | * @param result raw data to be put into the log message 44 | * @return line without newline 45 | */ 46 | public static String resultToString(SSLEngineResult result) { 47 | return String.format("status=%s,handshakeStatus=%s,bytesConsumed=%d,bytesConsumed=%d", result.getStatus(), 48 | result.getHandshakeStatus(), result.bytesProduced(), result.bytesConsumed()); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/services/jdk.incubator.sql2.DataSourceFactory: -------------------------------------------------------------------------------- 1 | org.postgresql.adba.PgDataSourceFactory -------------------------------------------------------------------------------- /src/test/java/org/postgresql/adba/LoggingTest.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertTrue; 4 | 5 | import java.util.logging.Level; 6 | import java.util.logging.Logger; 7 | import jdk.incubator.sql2.DataSource; 8 | import jdk.incubator.sql2.Session; 9 | import org.junit.jupiter.api.AfterAll; 10 | import org.junit.jupiter.api.BeforeAll; 11 | import org.junit.jupiter.api.Test; 12 | import org.postgresql.adba.testutil.ConnectUtil; 13 | import org.postgresql.adba.testutil.DatabaseHolder; 14 | import org.postgresql.adba.util.TestLogHandler; 15 | import org.testcontainers.containers.PostgreSQLContainer; 16 | 17 | public class LoggingTest { 18 | public static PostgreSQLContainer postgres = DatabaseHolder.getCached(); 19 | 20 | private static DataSource ds; 21 | 22 | @BeforeAll 23 | public static void setUp() { 24 | ds = ConnectUtil.openDb(postgres); 25 | } 26 | 27 | @AfterAll 28 | public static void tearDown() { 29 | ds.close(); 30 | } 31 | 32 | @Test 33 | public void supplyLogger() { 34 | try (Session session = ds.getSession()) { 35 | 36 | Logger logger = Logger.getLogger("my junit-test logger"); 37 | TestLogHandler handler = new TestLogHandler(); 38 | handler.setLevel(Level.ALL); 39 | logger.setUseParentHandlers(false); 40 | logger.addHandler(handler); 41 | logger.setLevel(Level.ALL); 42 | 43 | session.logger(logger); 44 | 45 | assertTrue(handler.checkMessage().startsWith("logger for connection ")); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/test/java/org/postgresql/adba/communication/packets/RowDescriptionTest.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.communication.packets; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.postgresql.adba.communication.packets.parts.ColumnTypes; 5 | import org.postgresql.adba.communication.packets.parts.FormatCodeTypes; 6 | 7 | import static org.junit.jupiter.api.Assertions.assertEquals; 8 | 9 | public class RowDescriptionTest { 10 | 11 | @Test 12 | public void describeSelect1() { 13 | byte[] bytes = new byte[] {0x00, 0x01, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 14 | 0x04, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, 0x00, 0x00}; 15 | 16 | RowDescription instance = new RowDescription(bytes); 17 | 18 | assertEquals(1, instance.getDescriptions().length); 19 | assertEquals("t", instance.getDescriptions()[0].getName()); 20 | assertEquals(0, instance.getDescriptions()[0].getObjectIdOfTable()); 21 | assertEquals(0, instance.getDescriptions()[0].getAttributeNumberOfColumn()); 22 | assertEquals(ColumnTypes.INT4, instance.getDescriptions()[0].getColumnType()); 23 | assertEquals(4, instance.getDescriptions()[0].getDataTypeSize()); 24 | assertEquals(-1, instance.getDescriptions()[0].getTypeModifier()); 25 | assertEquals(FormatCodeTypes.TEXT, instance.getDescriptions()[0].getFormatCode()); 26 | } 27 | } -------------------------------------------------------------------------------- /src/test/java/org/postgresql/adba/communication/packets/parsers/TextParserTest.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.communication.packets.parsers; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertArrayEquals; 4 | 5 | import org.junit.jupiter.api.Test; 6 | 7 | public class TextParserTest { 8 | @Test 9 | public void textArrayOut() { 10 | Object[] result = (Object[])TextParser.textArrayOut("{first,\"\\\"second\",\"th,ird\"}", String[].class); 11 | 12 | assertArrayEquals(new String[] {"first", "\"second", "th,ird"}, result); 13 | } 14 | 15 | @Test 16 | public void textArrayOutEmptyArray() { 17 | Object[] result = (Object[])TextParser.textArrayOut("{}", String[].class); 18 | 19 | assertArrayEquals(new String[] {}, result); 20 | } 21 | 22 | @Test 23 | public void textArrayOutArrayOfEmptyStringsOne() { 24 | Object[] result = (Object[])TextParser.textArrayOut("{\"\"}", String[].class); 25 | 26 | assertArrayEquals(new String[] {""}, result); 27 | } 28 | 29 | @Test 30 | public void textArrayOutArrayOfEmptyStringsTwo() { 31 | Object[] result = (Object[])TextParser.textArrayOut("{,}", String[].class); 32 | 33 | assertArrayEquals(new String[] {"", ""}, result); 34 | } 35 | 36 | @Test 37 | public void textArrayOutArrayOfEmptyStringsThree() { 38 | Object[] result = (Object[])TextParser.textArrayOut("{,,}", String[].class); 39 | 40 | assertArrayEquals(new String[] {"", "", ""}, result); 41 | } 42 | 43 | @Test 44 | public void textArrayOutArrayOfEmptyFull() { 45 | Object[] result = (Object[])TextParser.textArrayOut("{,a}", String[].class); 46 | 47 | assertArrayEquals(new String[] {"", "a"}, result); 48 | } 49 | 50 | @Test 51 | public void textArrayOutArrayOfFullEmpty() { 52 | Object[] result = (Object[])TextParser.textArrayOut("{a,}", String[].class); 53 | 54 | assertArrayEquals(new String[] {"a", ""}, result); 55 | } 56 | 57 | @Test 58 | public void textArrayOutWithUnicode() { 59 | Object[] result = (Object[])TextParser.textArrayOut("{a1,ö2}", String[].class); 60 | 61 | assertArrayEquals(new String[] {"a1", "ö2"}, result); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/test/java/org/postgresql/adba/pgdatatypes/BoxTest.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.pgdatatypes; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import org.junit.jupiter.api.Test; 6 | 7 | public class BoxTest { 8 | @Test 9 | public void equals() { 10 | Box b1 = new Box(1, 2, 3, 4); 11 | Box b2 = new Box(1, 2, 3, 4); 12 | 13 | assertEquals(b1, b2); 14 | } 15 | } -------------------------------------------------------------------------------- /src/test/java/org/postgresql/adba/pgdatatypes/CircleTest.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.pgdatatypes; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import org.junit.jupiter.api.Test; 6 | 7 | public class CircleTest { 8 | 9 | @Test 10 | public void equals() { 11 | Circle c1 = new Circle(1, 2, 3); 12 | Circle c2 = new Circle(1, 2, 3); 13 | 14 | assertEquals(c1, c2); 15 | } 16 | } -------------------------------------------------------------------------------- /src/test/java/org/postgresql/adba/pgdatatypes/LineSegmentTest.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.pgdatatypes; 2 | 3 | 4 | import static org.junit.jupiter.api.Assertions.assertEquals; 5 | 6 | import org.junit.jupiter.api.Test; 7 | 8 | public class LineSegmentTest { 9 | @Test 10 | public void equals() { 11 | LineSegment ls1 = new LineSegment(1, 2, 3, 4); 12 | LineSegment ls2 = new LineSegment(1, 2, 3, 4); 13 | 14 | assertEquals(ls1, ls2); 15 | } 16 | } -------------------------------------------------------------------------------- /src/test/java/org/postgresql/adba/pgdatatypes/LineTest.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.pgdatatypes; 2 | 3 | 4 | import static org.junit.jupiter.api.Assertions.assertEquals; 5 | 6 | import org.junit.jupiter.api.Test; 7 | 8 | public class LineTest { 9 | 10 | @Test 11 | public void equals() { 12 | Line l1 = new Line(1, 2, 3); 13 | Line l2 = new Line(1, 2, 3); 14 | 15 | assertEquals(l1, l2); 16 | } 17 | } -------------------------------------------------------------------------------- /src/test/java/org/postgresql/adba/pgdatatypes/PathTest.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.pgdatatypes; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertNotEquals; 5 | 6 | import org.junit.jupiter.api.Test; 7 | 8 | public class PathTest { 9 | 10 | @Test 11 | public void equals() { 12 | Path p1 = new Path(true, new Point(1, 2)); 13 | Path p2 = new Path(true, new Point(1, 2)); 14 | 15 | assertEquals(p1, p2); 16 | } 17 | 18 | @Test 19 | public void equalsFalse1() { 20 | Path p1 = new Path(true, new Point(1, 2)); 21 | Path p2 = new Path(false, new Point(1, 2)); 22 | 23 | assertNotEquals(p1, p2); 24 | } 25 | 26 | @Test 27 | public void equalsFalse2() { 28 | Path p1 = new Path(true, new Point(1, 2)); 29 | Path p2 = new Path(true, new Point(2, 1)); 30 | 31 | assertNotEquals(p1, p2); 32 | } 33 | 34 | @Test 35 | public void equalsFalse3() { 36 | Path p1 = new Path(true, new Point(1, 2)); 37 | Path p2 = new Path(true, new Point(1, 2), new Point(1, 2)); 38 | 39 | assertNotEquals(p1, p2); 40 | } 41 | } -------------------------------------------------------------------------------- /src/test/java/org/postgresql/adba/pgdatatypes/PointTest.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.pgdatatypes; 2 | 3 | 4 | import static org.junit.jupiter.api.Assertions.assertEquals; 5 | 6 | import org.junit.jupiter.api.Test; 7 | 8 | public class PointTest { 9 | 10 | @Test 11 | public void equals() { 12 | Point p1 = new Point(1, 2); 13 | Point p2 = new Point(1, 2); 14 | 15 | assertEquals(p1, p2); 16 | } 17 | } -------------------------------------------------------------------------------- /src/test/java/org/postgresql/adba/pgdatatypes/PolygonTest.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.pgdatatypes; 2 | 3 | 4 | import static org.junit.jupiter.api.Assertions.assertEquals; 5 | 6 | import org.junit.jupiter.api.Test; 7 | 8 | public class PolygonTest { 9 | 10 | @Test 11 | public void equals() { 12 | Polygon p1 = new Polygon(new Point(1, 2)); 13 | Polygon p2 = new Polygon(new Point(1, 2)); 14 | 15 | assertEquals(p1, p2); 16 | } 17 | } -------------------------------------------------------------------------------- /src/test/java/org/postgresql/adba/testutil/CollectorUtils.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.testutil; 2 | 3 | import java.util.List; 4 | import java.util.stream.Collector; 5 | import jdk.incubator.sql2.Result; 6 | import jdk.incubator.sql2.SqlType; 7 | import org.postgresql.adba.util.PgCount; 8 | 9 | public class CollectorUtils { 10 | 11 | /** 12 | * Returns first element that was collected. 13 | * @param clazz type of element to fetch 14 | * @param returning type 15 | * @return a collector 16 | */ 17 | public static Collector singleCollector(Class clazz) { 18 | return Collector.of( 19 | () -> (T[])new Object[1], 20 | (a, r) -> a[0] = r.at("t").get(clazz), 21 | (l, r) -> null, 22 | a -> a[0]); 23 | } 24 | 25 | /** 26 | * Returns sum of elements that was collected. 27 | * @return a collector 28 | */ 29 | public static Collector summingCollector() { 30 | return Collector.of( 31 | () -> new Integer[] {0}, 32 | (a, r) -> a[0] += r, 33 | (l, r) -> null, 34 | a -> a[0]); 35 | } 36 | 37 | /** 38 | * Returns a sum of the affected rows that was collected. 39 | * @return a collector 40 | */ 41 | public static Collector summingCountCollector() { 42 | return Collector.of( 43 | () -> new Integer[] {0}, 44 | (a, r) -> a[0] += (int)r.getCount(), 45 | (l, r) -> null, 46 | a -> a[0]); 47 | } 48 | 49 | /** 50 | * Collector. 51 | * @return a collector 52 | */ 53 | public static Collector, ?, Integer> summingCountListCollector() { 54 | return Collector.of( 55 | () -> new Integer[] {0}, 56 | (a, r) -> r.stream().forEach(c -> a[0] += (int)c.getCount()), 57 | (l, r) -> null, 58 | a -> a[0]); 59 | } 60 | 61 | /** 62 | * Returns the java type of the column named "t". 63 | * @param clazz type of element to fetch 64 | * @param returning type 65 | * @return a collector 66 | */ 67 | public static Collector[], Class> javaTypeCollector(Class clazz) { 68 | return Collector.of( 69 | () -> new Class[1], 70 | (a, r) -> a[0] = r.at("t").javaType(), 71 | (l, r) -> null, 72 | a -> a[0]); 73 | } 74 | 75 | /** 76 | * Returns the sql type of the column named "t". 77 | * @return a collector 78 | */ 79 | public static Collector adbaTypeCollector() { 80 | return Collector.of( 81 | () -> new SqlType[1], 82 | (a, r) -> a[0] = r.at("t").sqlType(), 83 | (l, r) -> null, 84 | a -> a[0]); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/test/java/org/postgresql/adba/testutil/ConnectUtil.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.testutil; 2 | 3 | import jdk.incubator.sql2.AdbaSessionProperty; 4 | import jdk.incubator.sql2.DataSource; 5 | import jdk.incubator.sql2.DataSourceFactory; 6 | import org.postgresql.adba.PgSessionProperty; 7 | import org.testcontainers.containers.PostgreSQLContainer; 8 | 9 | public class ConnectUtil { 10 | 11 | /** 12 | * Opens a DataSource to the supplied database. 13 | * @param postgres the docker database 14 | * @return a datasource 15 | */ 16 | public static DataSource openDb(PostgreSQLContainer postgres) { 17 | return DataSourceFactory.newFactory("org.postgresql.adba.PgDataSourceFactory") 18 | .builder() 19 | .url("jdbc:postgresql://" + postgres.getContainerIpAddress() + ":" + postgres.getMappedPort(5432) 20 | + "/" + postgres.getDatabaseName()) 21 | .username(postgres.getUsername()) 22 | .password(postgres.getPassword()) 23 | .sessionProperty(AdbaSessionProperty.TRANSACTION_ISOLATION, 24 | AdbaSessionProperty.TransactionIsolation.REPEATABLE_READ) 25 | .build(); 26 | } 27 | 28 | /** 29 | * Opens a DataSource to the supplied database that sends all traffic over tls. 30 | * @param postgres the docker database 31 | * @return a datasource 32 | */ 33 | public static DataSource openDbWithTls(PostgreSQLContainer postgres) { 34 | return DataSourceFactory.newFactory("org.postgresql.adba.PgDataSourceFactory") 35 | .builder() 36 | .url("jdbc:postgresql://" + postgres.getContainerIpAddress() + ":" + postgres.getMappedPort(5432) 37 | + "/" + postgres.getDatabaseName()) 38 | .username(postgres.getUsername()) 39 | .password(postgres.getPassword()) 40 | .sessionProperty(AdbaSessionProperty.TRANSACTION_ISOLATION, 41 | AdbaSessionProperty.TransactionIsolation.REPEATABLE_READ) 42 | .sessionProperty(PgSessionProperty.SSL, true) 43 | .build(); 44 | } 45 | 46 | public static void createTable(DataSource ds, String tab, String idInt, String s, String answerInt) { 47 | 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/test/java/org/postgresql/adba/testutil/DatabaseHolder.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.testutil; 2 | 3 | import static java.util.Collections.singletonMap; 4 | 5 | import org.testcontainers.containers.PostgreSQLContainer; 6 | 7 | public class DatabaseHolder { 8 | private static PostgreSQLContainer postgres = new PostgreSQLContainer(); 9 | 10 | static { 11 | postgres.withTmpFs(singletonMap("/var/lib/postgresql/data", "rw")); 12 | postgres.start(); 13 | } 14 | 15 | public static PostgreSQLContainer getCached() { 16 | return postgres; 17 | } 18 | 19 | /** 20 | * returns a new database, instead of the cached one. 21 | * @return a docker instance running a postgresql database 22 | */ 23 | public static PostgreSQLContainer getNew() { 24 | PostgreSQLContainer container = new PostgreSQLContainer(); 25 | container.withTmpFs(singletonMap("/var/lib/postgresql/data", "rw")); 26 | container.start(); 27 | return container; 28 | } 29 | 30 | /** 31 | * returns a new database that requires TLS, instead of the cached one. 32 | * @return a docker instance running a postgresql database 33 | */ 34 | public static PostgreSQLContainer getNewWithTls() { 35 | PostgreSQLContainer container = new PostgreSQLContainer("capitol/postgresql-tls:debian-stretch-postgresql10"); 36 | container.withTmpFs(singletonMap("/var/lib/postgresql/data", "rw")); 37 | container.start(); 38 | 39 | return container; 40 | } 41 | 42 | /** 43 | * returns a new database that that runs postgresql 11. 44 | * @return a docker instance running a postgresql 11 database 45 | */ 46 | public static PostgreSQLContainer getNew11() { 47 | PostgreSQLContainer container = new PostgreSQLContainer("capitol/debian-buster-postgresql11-tls:latest"); 48 | container.withTmpFs(singletonMap("/var/lib/postgresql/data", "rw")); 49 | container.start(); 50 | 51 | return container; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/test/java/org/postgresql/adba/testutil/FutureUtil.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.testutil; 2 | 3 | import java.util.concurrent.CompletionStage; 4 | import java.util.concurrent.ExecutionException; 5 | import java.util.concurrent.TimeUnit; 6 | import java.util.concurrent.TimeoutException; 7 | 8 | public class FutureUtil { 9 | public static T get10(CompletionStage cs) throws InterruptedException, ExecutionException, TimeoutException { 10 | return cs.toCompletableFuture().get(10, TimeUnit.SECONDS); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/test/java/org/postgresql/adba/testutil/SimpleRowSubscriber.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.testutil; 2 | 3 | import java.util.concurrent.CountDownLatch; 4 | import java.util.concurrent.Flow; 5 | import java.util.function.Consumer; 6 | import jdk.incubator.sql2.Result; 7 | 8 | public class SimpleRowSubscriber implements Flow.Subscriber { 9 | 10 | private Flow.Subscription subscription; 11 | private Integer columnTSum = 0; 12 | private int demand = 0; 13 | private Consumer fail; 14 | private CountDownLatch conditionLatch = new CountDownLatch(1); 15 | 16 | public SimpleRowSubscriber(Consumer fail) { 17 | this.fail = fail; 18 | } 19 | 20 | @Override 21 | public void onSubscribe(Flow.Subscription subscription) { 22 | this.subscription = subscription; 23 | this.subscription.request(10); 24 | demand += 10; 25 | } 26 | 27 | @Override 28 | public void onNext(Result.RowColumn column) { 29 | columnTSum += column.at("t").get(Integer.class); 30 | if (--demand < 1) { 31 | subscription.request(10); 32 | demand += 10; 33 | } 34 | } 35 | 36 | @Override 37 | public void onError(Throwable throwable) { 38 | fail.accept(throwable.getMessage()); 39 | } 40 | 41 | @Override 42 | public void onComplete() { 43 | conditionLatch.countDown(); 44 | } 45 | 46 | public Integer getColumnTSum() throws InterruptedException { 47 | conditionLatch.await(); 48 | return columnTSum; 49 | } 50 | } 51 | 52 | -------------------------------------------------------------------------------- /src/test/java/org/postgresql/adba/util/PreparedStatementCacheTest.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.util; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.postgresql.adba.communication.PreparedStatementCache; 5 | 6 | import java.util.Arrays; 7 | 8 | import static org.junit.jupiter.api.Assertions.assertEquals; 9 | import static org.junit.jupiter.api.Assertions.assertThrows; 10 | 11 | public class PreparedStatementCacheTest { 12 | 13 | @Test 14 | public void getNameForQuery() { 15 | PreparedStatementCache cache = new PreparedStatementCache(); 16 | 17 | String name = cache.getQuery("select 1", Arrays.asList(1, 2)).getQueryName(); 18 | assertEquals(name, cache.getQuery("select 1", Arrays.asList(1, 2)).getQueryName()); 19 | assertEquals(name, cache.getQuery("select 1", Arrays.asList(1, 2)).getQueryName()); 20 | } 21 | 22 | @Test 23 | public void getNameForQueryNull() { 24 | PreparedStatementCache cache = new PreparedStatementCache(); 25 | 26 | assertThrows(IllegalArgumentException.class, () -> cache.getQuery(null, Arrays.asList(1, 2))); 27 | } 28 | } -------------------------------------------------------------------------------- /src/test/java/org/postgresql/adba/util/TestLogHandler.java: -------------------------------------------------------------------------------- 1 | package org.postgresql.adba.util; 2 | 3 | import java.util.logging.Handler; 4 | import java.util.logging.Level; 5 | import java.util.logging.LogRecord; 6 | 7 | public class TestLogHandler extends Handler { 8 | private Level lastLevel = Level.FINEST; 9 | private String lastMessage = null; 10 | 11 | public Level checkLevel() { 12 | return lastLevel; 13 | } 14 | 15 | public String checkMessage() { 16 | return lastMessage; 17 | } 18 | 19 | public void publish(LogRecord record) { 20 | lastLevel = record.getLevel(); 21 | lastMessage = record.getMessage(); 22 | } 23 | 24 | public void close() { 25 | } 26 | 27 | public void flush() { 28 | } 29 | } -------------------------------------------------------------------------------- /src/test/resources/debian-buster-postgresql11-tls/generate_cert.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | openssl genrsa -out rootCA.key 4096 4 | 5 | # use 100 years, in order to make our unit tests work longer than I live 6 | openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 36500 -out rootCA.crt -subj '/CN=localhost' 7 | 8 | openssl genrsa -out localhost.key 2048 9 | 10 | openssl req -new -key localhost.key -out localhost.csr -subj '/CN=localhost' 11 | 12 | openssl x509 -req -in localhost.csr -text -days 36500 -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -out localhost.crt 13 | -------------------------------------------------------------------------------- /src/test/resources/debian-buster-postgresql11-tls/localhost.csr: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIICWTCCAUECAQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0B 3 | AQEFAAOCAQ8AMIIBCgKCAQEAtvrrRHUY9ArO+L9dYCNjonyFVFrvYSOpKMjh/U/b 4 | +7T0CXUAnETDqGr1XF8YlC5vt5bQC6L+MeU9k6TMz/YKi3NnoIReAJWJSDUthe4K 5 | LmI7KWPCgXrA6OSS2W0LZYp4Fhc+3GKMolywcnH+TrfJYQWnCDEwzIcFjlvG7MhY 6 | 2a9D+ImCL9fB2eBLn29mC6bpQ8bawVwdsnbJjNf4dgBpgAQ+5Xw+IWiKwG8dflfb 7 | +FYI6VWtgbGGDXujGpjS6Ai7DMMJNhOI+NXQGQHdT3u2k8/elJqxN1/Wj0Bg8o8A 8 | MHfTJUZQgFqedUqcla7nu1Fj/+yUFiMep39eFVTj0Ng9owIDAQABoAAwDQYJKoZI 9 | hvcNAQELBQADggEBAFtO7TA3cY1K6kmwHTrqOlB8FA00qze8AIgWWqBG8a8fZQz4 10 | YYLFDOi/WScaA7mwxInHvJIaidwOeNhIcjXZoY/XWqGKezvvdjBGySGfoubY8wQq 11 | xWuw8NJFmok5AWyasH95jM0SMnFZEgO4oI3oH7OEaKXKdiHyng/cy9cANvs/Uksn 12 | A0t0RZCv9oSZIDHKeNmv4DNcU+SyH1NgzdWxW5uuHl4nRaU18KMjCg1qtFIl6eoo 13 | uId9+Sg7j865t0DaJIegks12rbC+r5kdbu6LAMr9UyuNi6svJ3H0RrMP7hGgrwd7 14 | odL6sY7yduUZnjr9bMiHMfBvhVl9Mp2QrH9LUHE= 15 | -----END CERTIFICATE REQUEST----- 16 | -------------------------------------------------------------------------------- /src/test/resources/debian-buster-postgresql11-tls/localhost.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEowIBAAKCAQEAtvrrRHUY9ArO+L9dYCNjonyFVFrvYSOpKMjh/U/b+7T0CXUA 3 | nETDqGr1XF8YlC5vt5bQC6L+MeU9k6TMz/YKi3NnoIReAJWJSDUthe4KLmI7KWPC 4 | gXrA6OSS2W0LZYp4Fhc+3GKMolywcnH+TrfJYQWnCDEwzIcFjlvG7MhY2a9D+ImC 5 | L9fB2eBLn29mC6bpQ8bawVwdsnbJjNf4dgBpgAQ+5Xw+IWiKwG8dflfb+FYI6VWt 6 | gbGGDXujGpjS6Ai7DMMJNhOI+NXQGQHdT3u2k8/elJqxN1/Wj0Bg8o8AMHfTJUZQ 7 | gFqedUqcla7nu1Fj/+yUFiMep39eFVTj0Ng9owIDAQABAoIBACwvt7SWWmpEWeqz 8 | u4bFxP+t9jyCoR/iDq1spTYYnNTRw8Ss3nLeICmBerLNvA+8jvnUj3Tf7WZ7Jz2K 9 | JHNrxOwb+EBI9rJJahdn0BBxhT/iNMsv7f56eC9FUzjyHjhtEcaz4lgx7CghHfLl 10 | GDZGJ3kodkeCKXiaensAKq9vShV21vXPolullsmcO/dVIxcD+Qfk0N7T0iCJ5hVI 11 | Rayh9q4nalgnxiPtVk4CcMT2KIuKOZbl6l8ncLQvHoq3zaqwZeBf3Awss+McjM0x 12 | SLDasj7JaCME9GSEQj1Ng97SWGpnptpToDgrxVrdunBP5NypviEnGXTaQdU4G1dt 13 | 6WVG/IECgYEA2/dO3HwTFI+u1P+aoR1iGHpeLjTHhYyX6O6AYfeoq5J3zHNxt0sJ 14 | SD8t9i4MLCm9ZKIbBjaPQZSpVX5Ml25wyIgSbpYk/2OVt4Kjv5C3hJgNc5ZUOYWU 15 | MKqVZB1tE8RBuoD1TueEBhEFcAhoMeGA7oSxVOJ3/9fUQy/M7SHHXiECgYEA1PSJ 16 | nYdh5lbLPQuLfExlOzn2nxi3pfTTJ+9o+kjGIy/u2m5iKbvR2KDAzSBeGlixmVuF 17 | j02xVFzfVEcT1jz3FbyprIPGCC2/862YSWKz+B1IFKv0Xj3/bloseRcoutCx6zAZ 18 | 1mkelfR6JSzMNRThAp4vEp8tndU73tOnEp3ZO0MCgYEAo+h2AEAIa8LhcWCCFdpy 19 | VXEhquazYmWwcOcADYBhVHARCu1faEjmwsopco8/jM0RjuJopsmTGDgxsj4pzpGC 20 | Qzt6GKOTMCdB0fvsDvxEc+5l36K+YhqSoW0LYw22UQtmOxaLNN+5dlfKqH/rPHgf 21 | /hwsk+cpqiBm0CXXW0BXcmECgYAN5qCNDedQF95Qb859IKeDBDebDwv940tdUf1y 22 | SQnWBiz7STVTMBV0pJmxSimaYqvFLPo87n9i2GUjpTggRf6DBru0rS1iH0pmZ7CH 23 | KdBBo/eukcLz2+wukehRRze7aiATECK/okEC3OCUSKZT2LcPaq/78TQTF3Y/B2Xi 24 | izdA7QKBgG5ecWIq3LqnzKzRP4aqBtFM3uU7pSIgNVFM/eSeBk3wRIBtNPNxwqD4 25 | xbyCDzXgTZpLI5QqX6GA0c+A6o3dF+AaGIXUBkVZXTmkD+Y7z3gtn+/mfmIfDqbZ 26 | rfRfQPbqcfb3455QgkCbrlhLm99Bu64sR3YzTw3jZjvI44yBEq+H 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /src/test/resources/debian-buster-postgresql11-tls/rootCA.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFADCCAuigAwIBAgIJAI6bBYw+eipFMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV 3 | BAMMCWxvY2FsaG9zdDAgFw0xODA3MTQyMzQzNTBaGA8yMTE4MDYyMDIzNDM1MFow 4 | FDESMBAGA1UEAwwJbG9jYWxob3N0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC 5 | CgKCAgEAtoDPnS1xOeIU5t7K0FsLPeHdx7mVJwQ+qvQfqYHuY7VROC9SiTo++XOo 6 | r2wo7exjh6N+x3G+hG3hvAIe9FJGeRJWRE3GJ2FzhVUTH4RO3zL7ZugkOwJIdK+s 7 | y5VWMwsbJoVl+00XxbAkFX11Ub0a1LFG7issC2zn3AA9OYdtRjXdK/AoaOyx+AWG 8 | p/pfl0CMCUPAaAUXvHISHWx522libSo2jRiXQrIomwgesV1P/bQ7o3S9PhR0elqe 9 | LutENIvMQpb9CrZEIImOADL4IU5KgRP1aRNLPUTK6Z6bvaGJ47uvUqqyy/tNgEP9 10 | 3Ts7X4CMGzyr8WlVTCWYzxtKnO+ioH1utWLOHeisPjt9EoWZOzN8CoxLubt8BGST 11 | CdvP/6TnhJqcW5Lm+6C8XKg+7LnJDCT2Dh0OS8235RdGaI/qufisDEfq7FoOz6iY 12 | NUNFeWanNP6pFBinoJzc8rsbwx9kMFMIJQv4aQv0khuu23CXtLpxyhb5bk7MBL5U 13 | 9rQM6K46E/nmtQ2c0yHvp03RDS3SKNOPxzpKjXPSn3M7J21tpQF0zv12dKENV0sd 14 | cDt29h2QmeS7p7gE47LRoCDk26a4N8E8rV8VkV8T6NWAm7eudd56y/rjqrHZ9whz 15 | Xb1PU8lOhYCGa0Y+3gn5lew6efOpa8Ktcd845kHM9qmympRgtF8CAwEAAaNTMFEw 16 | HQYDVR0OBBYEFBZSeZgbo/FbDwNpbpycqe3QSf01MB8GA1UdIwQYMBaAFBZSeZgb 17 | o/FbDwNpbpycqe3QSf01MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQAD 18 | ggIBAF19a9M5I00gN5EogT8S6OPzdlNrhGc00vhDQ+kEznuIEhtlqP+J0ZLdCF6S 19 | 6UAMkYBo6Fgcqy+3cA0013Cyzo/Hhz5a6CqLy7aFpGU4ow/+Kk9qzD7FpDf3zRQM 20 | omZOZjMf3Tz6U7nom/c3mCqpKqf8mGgGyGteyLOJb3yA090FbAqZ9h04VXYF8mwq 21 | r7NC/Xpm5yI3DFKn4T1sfRTEvHNA5Kd3+sFt5Wi3FEQ8oZ9yhXZqyVuLoyfPX+KZ 22 | bLEP0L2JRxImSVdrmEMXNtPRXE1kbyfs68Iu2t1HiX7s48Ci3/SMypZD1J2MNNEq 23 | pDu153viMjfHvw/9i76h4JM7wU3kMU85hheO4k0BYTil9hykyotUmYhMtxVrRCPD 24 | FNk11gyNFHFXPTdFT3AvNSK8rLX93sPkXQlMHK2PI6DdHviMhBiG8W0m6EgzsZ7i 25 | 9onx73X9XdfyTNIacXtUgj/b2aZz7DXBWgt84Jp860PwJ3chXlT7gIgYHHX5t+lR 26 | YGvkYZAM6e396ismNFhoz2wfwHzgcCC0tTArsmfXNun9HM6GPqFpSSr0Barexy0h 27 | PwM+NPXP3cbgLFWJIXS03URtBYvAyKxX/adSoRTwWHjb9X6PKYvZ5phK1QeDkPL0 28 | tNQgI56noPmK98a/9laHMKHdqTwHFiG6eSH2GN1AJ6KcTqlq 29 | -----END CERTIFICATE----- 30 | -------------------------------------------------------------------------------- /src/test/resources/debian-buster-postgresql11-tls/rootCA.srl: -------------------------------------------------------------------------------- 1 | F28BF25B92502EFA 2 | -------------------------------------------------------------------------------- /src/test/resources/debian-stretch-postgresql10/generate_cert.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | openssl genrsa -out rootCA.key 4096 4 | 5 | # use 100 years, in order to make our unit tests work longer than I live 6 | openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 36500 -out rootCA.crt -subj '/CN=localhost' 7 | 8 | openssl genrsa -out localhost.key 2048 9 | 10 | openssl req -new -key localhost.key -out localhost.csr -subj '/CN=localhost' 11 | 12 | openssl x509 -req -in localhost.csr -text -days 36500 -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -out localhost.crt 13 | -------------------------------------------------------------------------------- /src/test/resources/debian-stretch-postgresql10/localhost.csr: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIICWTCCAUECAQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0B 3 | AQEFAAOCAQ8AMIIBCgKCAQEAtvrrRHUY9ArO+L9dYCNjonyFVFrvYSOpKMjh/U/b 4 | +7T0CXUAnETDqGr1XF8YlC5vt5bQC6L+MeU9k6TMz/YKi3NnoIReAJWJSDUthe4K 5 | LmI7KWPCgXrA6OSS2W0LZYp4Fhc+3GKMolywcnH+TrfJYQWnCDEwzIcFjlvG7MhY 6 | 2a9D+ImCL9fB2eBLn29mC6bpQ8bawVwdsnbJjNf4dgBpgAQ+5Xw+IWiKwG8dflfb 7 | +FYI6VWtgbGGDXujGpjS6Ai7DMMJNhOI+NXQGQHdT3u2k8/elJqxN1/Wj0Bg8o8A 8 | MHfTJUZQgFqedUqcla7nu1Fj/+yUFiMep39eFVTj0Ng9owIDAQABoAAwDQYJKoZI 9 | hvcNAQELBQADggEBAFtO7TA3cY1K6kmwHTrqOlB8FA00qze8AIgWWqBG8a8fZQz4 10 | YYLFDOi/WScaA7mwxInHvJIaidwOeNhIcjXZoY/XWqGKezvvdjBGySGfoubY8wQq 11 | xWuw8NJFmok5AWyasH95jM0SMnFZEgO4oI3oH7OEaKXKdiHyng/cy9cANvs/Uksn 12 | A0t0RZCv9oSZIDHKeNmv4DNcU+SyH1NgzdWxW5uuHl4nRaU18KMjCg1qtFIl6eoo 13 | uId9+Sg7j865t0DaJIegks12rbC+r5kdbu6LAMr9UyuNi6svJ3H0RrMP7hGgrwd7 14 | odL6sY7yduUZnjr9bMiHMfBvhVl9Mp2QrH9LUHE= 15 | -----END CERTIFICATE REQUEST----- 16 | -------------------------------------------------------------------------------- /src/test/resources/debian-stretch-postgresql10/localhost.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEowIBAAKCAQEAtvrrRHUY9ArO+L9dYCNjonyFVFrvYSOpKMjh/U/b+7T0CXUA 3 | nETDqGr1XF8YlC5vt5bQC6L+MeU9k6TMz/YKi3NnoIReAJWJSDUthe4KLmI7KWPC 4 | gXrA6OSS2W0LZYp4Fhc+3GKMolywcnH+TrfJYQWnCDEwzIcFjlvG7MhY2a9D+ImC 5 | L9fB2eBLn29mC6bpQ8bawVwdsnbJjNf4dgBpgAQ+5Xw+IWiKwG8dflfb+FYI6VWt 6 | gbGGDXujGpjS6Ai7DMMJNhOI+NXQGQHdT3u2k8/elJqxN1/Wj0Bg8o8AMHfTJUZQ 7 | gFqedUqcla7nu1Fj/+yUFiMep39eFVTj0Ng9owIDAQABAoIBACwvt7SWWmpEWeqz 8 | u4bFxP+t9jyCoR/iDq1spTYYnNTRw8Ss3nLeICmBerLNvA+8jvnUj3Tf7WZ7Jz2K 9 | JHNrxOwb+EBI9rJJahdn0BBxhT/iNMsv7f56eC9FUzjyHjhtEcaz4lgx7CghHfLl 10 | GDZGJ3kodkeCKXiaensAKq9vShV21vXPolullsmcO/dVIxcD+Qfk0N7T0iCJ5hVI 11 | Rayh9q4nalgnxiPtVk4CcMT2KIuKOZbl6l8ncLQvHoq3zaqwZeBf3Awss+McjM0x 12 | SLDasj7JaCME9GSEQj1Ng97SWGpnptpToDgrxVrdunBP5NypviEnGXTaQdU4G1dt 13 | 6WVG/IECgYEA2/dO3HwTFI+u1P+aoR1iGHpeLjTHhYyX6O6AYfeoq5J3zHNxt0sJ 14 | SD8t9i4MLCm9ZKIbBjaPQZSpVX5Ml25wyIgSbpYk/2OVt4Kjv5C3hJgNc5ZUOYWU 15 | MKqVZB1tE8RBuoD1TueEBhEFcAhoMeGA7oSxVOJ3/9fUQy/M7SHHXiECgYEA1PSJ 16 | nYdh5lbLPQuLfExlOzn2nxi3pfTTJ+9o+kjGIy/u2m5iKbvR2KDAzSBeGlixmVuF 17 | j02xVFzfVEcT1jz3FbyprIPGCC2/862YSWKz+B1IFKv0Xj3/bloseRcoutCx6zAZ 18 | 1mkelfR6JSzMNRThAp4vEp8tndU73tOnEp3ZO0MCgYEAo+h2AEAIa8LhcWCCFdpy 19 | VXEhquazYmWwcOcADYBhVHARCu1faEjmwsopco8/jM0RjuJopsmTGDgxsj4pzpGC 20 | Qzt6GKOTMCdB0fvsDvxEc+5l36K+YhqSoW0LYw22UQtmOxaLNN+5dlfKqH/rPHgf 21 | /hwsk+cpqiBm0CXXW0BXcmECgYAN5qCNDedQF95Qb859IKeDBDebDwv940tdUf1y 22 | SQnWBiz7STVTMBV0pJmxSimaYqvFLPo87n9i2GUjpTggRf6DBru0rS1iH0pmZ7CH 23 | KdBBo/eukcLz2+wukehRRze7aiATECK/okEC3OCUSKZT2LcPaq/78TQTF3Y/B2Xi 24 | izdA7QKBgG5ecWIq3LqnzKzRP4aqBtFM3uU7pSIgNVFM/eSeBk3wRIBtNPNxwqD4 25 | xbyCDzXgTZpLI5QqX6GA0c+A6o3dF+AaGIXUBkVZXTmkD+Y7z3gtn+/mfmIfDqbZ 26 | rfRfQPbqcfb3455QgkCbrlhLm99Bu64sR3YzTw3jZjvI44yBEq+H 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /src/test/resources/debian-stretch-postgresql10/rootCA.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFADCCAuigAwIBAgIJAI6bBYw+eipFMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV 3 | BAMMCWxvY2FsaG9zdDAgFw0xODA3MTQyMzQzNTBaGA8yMTE4MDYyMDIzNDM1MFow 4 | FDESMBAGA1UEAwwJbG9jYWxob3N0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC 5 | CgKCAgEAtoDPnS1xOeIU5t7K0FsLPeHdx7mVJwQ+qvQfqYHuY7VROC9SiTo++XOo 6 | r2wo7exjh6N+x3G+hG3hvAIe9FJGeRJWRE3GJ2FzhVUTH4RO3zL7ZugkOwJIdK+s 7 | y5VWMwsbJoVl+00XxbAkFX11Ub0a1LFG7issC2zn3AA9OYdtRjXdK/AoaOyx+AWG 8 | p/pfl0CMCUPAaAUXvHISHWx522libSo2jRiXQrIomwgesV1P/bQ7o3S9PhR0elqe 9 | LutENIvMQpb9CrZEIImOADL4IU5KgRP1aRNLPUTK6Z6bvaGJ47uvUqqyy/tNgEP9 10 | 3Ts7X4CMGzyr8WlVTCWYzxtKnO+ioH1utWLOHeisPjt9EoWZOzN8CoxLubt8BGST 11 | CdvP/6TnhJqcW5Lm+6C8XKg+7LnJDCT2Dh0OS8235RdGaI/qufisDEfq7FoOz6iY 12 | NUNFeWanNP6pFBinoJzc8rsbwx9kMFMIJQv4aQv0khuu23CXtLpxyhb5bk7MBL5U 13 | 9rQM6K46E/nmtQ2c0yHvp03RDS3SKNOPxzpKjXPSn3M7J21tpQF0zv12dKENV0sd 14 | cDt29h2QmeS7p7gE47LRoCDk26a4N8E8rV8VkV8T6NWAm7eudd56y/rjqrHZ9whz 15 | Xb1PU8lOhYCGa0Y+3gn5lew6efOpa8Ktcd845kHM9qmympRgtF8CAwEAAaNTMFEw 16 | HQYDVR0OBBYEFBZSeZgbo/FbDwNpbpycqe3QSf01MB8GA1UdIwQYMBaAFBZSeZgb 17 | o/FbDwNpbpycqe3QSf01MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQAD 18 | ggIBAF19a9M5I00gN5EogT8S6OPzdlNrhGc00vhDQ+kEznuIEhtlqP+J0ZLdCF6S 19 | 6UAMkYBo6Fgcqy+3cA0013Cyzo/Hhz5a6CqLy7aFpGU4ow/+Kk9qzD7FpDf3zRQM 20 | omZOZjMf3Tz6U7nom/c3mCqpKqf8mGgGyGteyLOJb3yA090FbAqZ9h04VXYF8mwq 21 | r7NC/Xpm5yI3DFKn4T1sfRTEvHNA5Kd3+sFt5Wi3FEQ8oZ9yhXZqyVuLoyfPX+KZ 22 | bLEP0L2JRxImSVdrmEMXNtPRXE1kbyfs68Iu2t1HiX7s48Ci3/SMypZD1J2MNNEq 23 | pDu153viMjfHvw/9i76h4JM7wU3kMU85hheO4k0BYTil9hykyotUmYhMtxVrRCPD 24 | FNk11gyNFHFXPTdFT3AvNSK8rLX93sPkXQlMHK2PI6DdHviMhBiG8W0m6EgzsZ7i 25 | 9onx73X9XdfyTNIacXtUgj/b2aZz7DXBWgt84Jp860PwJ3chXlT7gIgYHHX5t+lR 26 | YGvkYZAM6e396ismNFhoz2wfwHzgcCC0tTArsmfXNun9HM6GPqFpSSr0Barexy0h 27 | PwM+NPXP3cbgLFWJIXS03URtBYvAyKxX/adSoRTwWHjb9X6PKYvZ5phK1QeDkPL0 28 | tNQgI56noPmK98a/9laHMKHdqTwHFiG6eSH2GN1AJ6KcTqlq 29 | -----END CERTIFICATE----- 30 | -------------------------------------------------------------------------------- /src/test/resources/debian-stretch-postgresql10/rootCA.srl: -------------------------------------------------------------------------------- 1 | F28BF25B92502EFA 2 | -------------------------------------------------------------------------------- /src/test/resources/keystore.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pgjdbc/pgadba/1a8924deccf75f198ed859d439a9a884a36a10a5/src/test/resources/keystore.jks --------------------------------------------------------------------------------