Codebase list postgis-java / fcb5d96
New upstream version 2021.1.0 Bas Couwenberg 1 year, 9 months ago
190 changed file(s) with 12476 addition(s) and 11619 deletion(s). Raw diff Collapse all Expand all
0 #!/usr/bin/env bash
1
2 set -euf
3
4 sudo apt-get update
5 sudo apt-get install -y gnupg haveged
6
7 rm -rf ~/.gnupg
8 gpg --list-keys
9
10 cat >key-info <<EOF
11 %echo Generating a key
12 Key-Type: RSA
13 Key-Length: 4096
14 Subkey-Type: RSA
15 Subkey-Length: 4096
16 Name-Real: PostGIS Development Team
17 Name-Comment: PostGIS Development Team
18 Name-Email: test-key@postgis.net
19 Expire-Date: 0
20 %no-ask-passphrase
21 %no-protection
22 %commit
23 %echo done
24 EOF
25
26 gpg --verbose --batch --gen-key key-info
27
28 echo -e "5\ny\n" | gpg --no-tty --command-fd 0 --expert --edit-key test-key@postgis.net trust;
29
30 # test
31 gpg --list-keys
32 gpg -e -a -r test-key@postgis.net key-info
33 rm key-info
34 gpg -d key-info.asc
35 rm key-info.asc
36
37 set +euf
0 #!/usr/bin/env bash
1
2 set -euf
3
4 MAVEN_BASE_URL=https://archive.apache.org/dist/maven/maven-3/
5 MAVEN_VERSION=3.8.1
6 MAVEN_SHA=b98a1905eb554d07427b2e5509ff09bd53e2f1dd7a0afa38384968b113abef02
7
8 sudo apt-get update
9 sudo apt-get install -y curl
10 sudo mkdir -p /usr/share/maven /usr/share/maven/ref
11 sudo curl -fsSL -o /tmp/apache-maven.tar.gz ${MAVEN_BASE_URL}/${MAVEN_VERSION}/binaries/apache-maven-${MAVEN_VERSION}-bin.tar.gz
12 echo "${MAVEN_SHA} /tmp/apache-maven.tar.gz" | sha256sum -c -
13 sudo tar -xzf /tmp/apache-maven.tar.gz -C /usr/share/maven --strip-components=1
14 sudo rm -f /tmp/apache-maven.tar.gz
15 sudo ln -fs /usr/share/maven/bin/mvn /usr/bin/mvn
16 mvn -version
17
18 set +euf
19
0 #!/usr/bin/env bash
1
2 set -euf
3
4 AZUL_GPG_KEY=0xB1998361219BD9C9
5 ZULU_VERSION=11
6 ZULU_RELEASE=11.0.12-1
7
8 sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys ${AZUL_GPG_KEY}
9 sudo apt-add-repository 'deb http://repos.azulsystems.com/ubuntu stable main'
10 sudo apt-get update
11 sudo apt-get install -y zulu-repo
12 sudo apt-get update
13 sudo apt-get install -y zulu${ZULU_VERSION}=${ZULU_RELEASE}
14 sudo sed -i.orig -e "s/^hl /jre /g" -e "s/^jdkhl /jdk /g" /usr/lib/jvm/.zulu${ZULU_VERSION}-ca-amd64.jinfo
15 sudo update-java-alternatives --set zulu${ZULU_VERSION}-ca-amd64
16 export ALTERNATIVES_JAVAC=$(realpath /etc/alternatives/javac)
17 export JAVA_HOME=${ALTERNATIVES_JAVAC%/bin/javac}
18 export PATH=$JAVA_HOME/bin:$PATH
19 java -version
20
21 set +euf
22
0 #!/usr/bin/env bash
1
2 set -euf
3
4 AZUL_GPG_KEY=0xB1998361219BD9C9
5 ZULU_VERSION=8
6 ZULU_RELEASE=8.0.302-1
7
8 sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys ${AZUL_GPG_KEY}
9 sudo apt-add-repository 'deb http://repos.azulsystems.com/ubuntu stable main'
10 sudo apt-get update
11 sudo apt-get install -y zulu-repo
12 sudo apt-get update
13 sudo apt-get install -y zulu${ZULU_VERSION}=${ZULU_RELEASE}
14 sudo sed -i.orig -e "s/^hl /jre /g" -e "s/^jdkhl /jdk /g" /usr/lib/jvm/.zulu${ZULU_VERSION}-ca-amd64.jinfo
15 sudo update-java-alternatives --set zulu${ZULU_VERSION}-ca-amd64
16 export ALTERNATIVES_JAVAC=$(realpath /etc/alternatives/javac)
17 export JAVA_HOME=${ALTERNATIVES_JAVAC%/bin/javac}
18 export PATH=$JAVA_HOME/bin:$PATH
19 java -version
20
21 set +euf
22
0 <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
1 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2 xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
3 <servers>
4 <server>
5 <id>ossrh</id>
6 <username>${env.OSSRHU}</username>
7 <password>${env.OSSRHT}</password>
8 </server>
9 </servers>
10 <profiles>
11 <profile>
12 <id>gpg</id>
13 <properties>
14 <gpg.keyname>test-key@postgis.net</gpg.keyname>
15 </properties>
16 </profile>
17 <profile>
18 <id>sonatype-snapshots</id>
19 <repositories>
20 <repository>
21 <id>sonatype-snapshots</id>
22 <snapshots>
23 <enabled>true</enabled>
24 </snapshots>
25 <name>sonatype-snapshots</name>
26 <url>https://oss.sonatype.org/content/repositories/snapshots/</url>
27 </repository>
28 </repositories>
29 </profile>
30 <profile>
31 <id>sonatype-staging</id>
32 <repositories>
33 <repository>
34 <id>sonatype-staging</id>
35 <snapshots>
36 <enabled>true</enabled>
37 </snapshots>
38 <name>sonatype-staging</name>
39 <url>https://oss.sonatype.org/content/groups/staging/</url>
40 </repository>
41 </repositories>
42 </profile>
43 <profile>
44 <id>sonatype-releases</id>
45 <repositories>
46 <repository>
47 <id>sonatype-releases</id>
48 <snapshots>
49 <enabled>true</enabled>
50 </snapshots>
51 <name>sonatype-releases</name>
52 <url>https://oss.sonatype.org/content/groups/public/</url>
53 </repository>
54 </repositories>
55 </profile>
56 </profiles>
57
58 </settings>
0 name: PostGIS Java CI
1
2 on: [push, pull_request]
3
4 defaults:
5 run:
6 shell: bash
7
8 jobs:
9 build-codebase:
10 strategy:
11 matrix:
12 os: [ubuntu-20.04]
13 java_version: [8]
14 maven_version: [3.8.1]
15 include:
16 - os: ubuntu-20.04
17 java_version: 8
18 maven_version: 3.8.1
19 maven_deploy: true
20 name: Build on OS ${{ matrix.os }} with Maven ${{ matrix.maven_version }} using Zulu ${{ matrix.java_version }}
21 runs-on: ${{ matrix.os }}
22 env:
23 JAVA_HOME: /usr/lib/jvm/zulu${{ matrix.java_version }}-ca-amd64
24 MAVEN_HOME: /usr/share/maven
25 MAVEN_PROPS: -Djavadoc.path=`which javadoc`
26 PROFILES: gpg,release-sign-artifacts,sonatype-deployment,sonatype-snapshots,sonatype-staging,sonatype-releases
27 SETTINGS: .github/settings.xml
28
29 steps:
30 - name: Checkout Source
31 uses: actions/checkout@v2
32
33 - name: Install GPG and generate test key
34 run: .github/install-gpg.sh
35
36 - name: Install Zulu OpenJDK
37 run: .github/install-zulu${{ matrix.java_version }}.sh
38
39 - name: Install Maven
40 run: .github/install-maven.sh
41
42 - name: Setup Maven repository cache
43 uses: actions/cache@v2
44 env:
45 cache-name: m2repo
46 with:
47 path: ~/.m2/repository
48 key: ${{ env.cache-name }}-${{ hashFiles('**/pom.xml') }}
49 restore-keys: |
50 ${{ env.cache-name }}-
51
52 - name: Log github.ref
53 run: echo "${{ github.ref }}"
54
55 - name: Show Maven dependency tree
56 run: mvn -U -V -s ${{ env.SETTINGS }} -P${{ env.PROFILES }} ${{ env.MAVEN_PROPS }} dependency:tree
57
58 - name: Show Maven active profiles
59 run: mvn -U -V -s ${{ env.SETTINGS }} -P${{ env.PROFILES }} ${{ env.MAVEN_PROPS }} help:active-profiles
60
61 - name: Show Maven effective POM
62 run: mvn -U -V -s ${{ env.SETTINGS }} -P${{ env.PROFILES }} ${{ env.MAVEN_PROPS }} help:effective-pom
63
64 - name: Maven build/test
65 run: mvn -U -V -s ${{ env.SETTINGS }} -P${{ env.PROFILES }} ${{ env.MAVEN_PROPS }} clean install
66
67 - name: Maven generate site
68 run: mvn -U -V -s ${{ env.SETTINGS }} -P${{ env.PROFILES }} ${{ env.MAVEN_PROPS }} site site:stage
69
70 - name: Maven deploy
71 if: ${{ matrix.maven_deploy && (github.ref == 'refs/heads/main') && (github.event_name != 'pull_request') }}
72 env:
73 OSSRHU: ${{ secrets.OSSRHU }}
74 OSSRHT: ${{ secrets.OSSRHT }}
75 run: mvn -U -V -s ${{ env.SETTINGS }} -P${{ env.PROFILES }} ${{ env.MAVEN_PROPS }} deploy
+0
-19
.travis/install-maven.sh less more
0 #!/usr/bin/env bash
1
2 set -euf
3
4 MAVEN_BASE_URL=https://archive.apache.org/dist/maven/maven-3/
5 MAVEN_VERSION=3.6.3
6 MAVEN_SHA=26ad91d751b3a9a53087aefa743f4e16a17741d3915b219cf74112bf87a438c5
7
8 sudo apt-get update
9 sudo apt-get install -y curl
10 sudo mkdir -p /usr/share/maven /usr/share/maven/ref
11 sudo curl -fsSL -o /tmp/apache-maven.tar.gz ${MAVEN_BASE_URL}/${MAVEN_VERSION}/binaries/apache-maven-${MAVEN_VERSION}-bin.tar.gz
12 echo "${MAVEN_SHA} /tmp/apache-maven.tar.gz" | sha256sum -c -
13 sudo tar -xzf /tmp/apache-maven.tar.gz -C /usr/share/maven --strip-components=1
14 sudo rm -f /tmp/apache-maven.tar.gz
15 sudo ln -s /usr/share/maven/bin/mvn /usr/bin/mvn
16 mvn -version
17
18 set +euf
+0
-22
.travis/install-zulu.sh less more
0 #!/usr/bin/env bash
1
2 set -euf
3
4 AZUL_GPG_KEY=0xB1998361219BD9C9
5 ZULU_VERSION=11
6 ZULU_RELEASE=11.37+17
7 JAVA_HOME=/usr/lib/jvm/zulu-11-amd64
8
9 sudo apt-get update
10 sudo apt-get install -y gnupg2 locales
11 sudo locale-gen en_US.UTF-8
12 sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys ${AZUL_GPG_KEY}
13 echo "deb http://repos.azulsystems.com/ubuntu stable main" | sudo tee -a /etc/apt/sources.list.d/zulu.list
14 sudo apt-get update
15 sudo apt-get install -y zulu-${ZULU_VERSION}=${ZULU_RELEASE}
16 export ALTERNATIVES_JAVA=$(realpath /etc/alternatives/java)
17 export JAVA_HOME=${ALTERNATIVES_JAVA%/bin/java}
18 export PATH=$JAVA_HOME/bin:$PATH
19 java -version
20
21 set +euf
+0
-10
.travis.yml less more
0 dist: xenial
1 language: java
2 services: docker
3
4 install:
5 - source .travis/install-zulu.sh
6 - source .travis/install-maven.sh
7
8 script:
9 - mvn -U -V clean install
0 <?xml version="1.0"?>
1 <!--
2 Copyright (c) 2016 Luminosity Labs LLC. All rights reserved.
3
4 Licensed to the Apache Software Foundation (ASF) under one or more
5 contributor license agreements. See the NOTICE file distributed with this
6 work for additional information regarding copyright ownership. The ASF
7 licenses this file to you under the Apache License, Version 2.0
8 (the "License"); you may not use this file except in compliance with the
9 License. You may obtain a copy of the License at
10 http://www.apache.org/licenses/LICENSE-2.0
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 License for the specific language governing permissions and limitations
15 under the License.
16 -->
17 <!DOCTYPE module PUBLIC
18 "-//Puppy Crawl//DTD Check Configuration 1.3//EN"
19 "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
20 <module name="Checker">
21 <!--
22 If you set the basedir property below, then all reported file
23 names will be relative to the specified directory. See
24 http://checkstyle.sourceforge.net/5.x/config.html#Checker
25 <property name="basedir" value="${basedir}"/>
26 -->
27
28 <property name="fileExtensions" value="java, properties, xml"/>
29
30 <!-- Enable suppression with @SuppressWarnings annotations-->
31 <module name="SuppressWarningsFilter"/>
32
33 <!-- Checks that a package-info.java file exists for each package. -->
34 <!-- See http://checkstyle.sf.net/config_javadoc.html#JavadocPackage -->
35 <module name="JavadocPackage"/>
36
37 <!-- Checks whether files end with a new line. -->
38 <!-- See http://checkstyle.sf.net/config_misc.html#NewlineAtEndOfFile -->
39 <module name="NewlineAtEndOfFile"/>
40
41 <!-- Checks that property files contain the same keys. -->
42 <!-- See http://checkstyle.sf.net/config_misc.html#Translation -->
43 <module name="Translation"/>
44
45 <!-- Checks for Size Violations. -->
46 <!-- See http://checkstyle.sf.net/config_sizes.html -->
47 <module name="FileLength"/>
48 <module name="LineLength">
49 <property name="max" value="120"/>
50 </module>
51
52 <!-- Checks for whitespace -->
53 <!-- See http://checkstyle.sf.net/config_whitespace.html -->
54 <module name="FileTabCharacter"/>
55
56 <!-- Miscellaneous other checks. -->
57 <!-- See http://checkstyle.sf.net/config_misc.html -->
58 <module name="RegexpSingleline">
59 <property name="format" value="\s+$"/>
60 <property name="minimum" value="0"/>
61 <property name="maximum" value="0"/>
62 <property name="message" value="Line has trailing spaces."/>
63 </module>
64
65 <!-- Checks for Headers -->
66 <!-- See http://checkstyle.sf.net/config_header.html -->
67 <!-- <module name="Header"> -->
68 <!-- <property name="headerFile" value="${checkstyle.header.file}"/> -->
69 <!-- <property name="fileExtensions" value="java"/> -->
70 <!-- </module> -->
71
72
73 <module name="TreeWalker">
74
75 <!-- Make annotations available for filtering via SuppressWarningsFilter -->
76 <module name="SuppressWarningsHolder"/>
77
78 <!-- Checks for Javadoc comments. -->
79 <!-- See http://checkstyle.sf.net/config_javadoc.html -->
80 <module name="JavadocMethod"/>
81 <module name="JavadocType"/>
82 <module name="JavadocVariable"/>
83 <module name="JavadocStyle"/>
84
85 <!-- Checks for Naming Conventions. -->
86 <!-- See http://checkstyle.sf.net/config_naming.html -->
87 <module name="ConstantName">
88 <property name="format" value="^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*|logger$"/>
89 </module>
90 <module name="LocalFinalVariableName"/>
91 <module name="LocalVariableName"/>
92 <module name="MemberName"/>
93 <module name="MethodName"/>
94 <module name="PackageName"/>
95 <module name="ParameterName"/>
96 <module name="StaticVariableName"/>
97 <module name="TypeName"/>
98
99 <!-- Checks for imports -->
100 <!-- See http://checkstyle.sf.net/config_import.html -->
101 <module name="AvoidStarImport"/>
102 <module name="IllegalImport"/> <!-- defaults to sun.* packages -->
103 <module name="RedundantImport"/>
104 <module name="UnusedImports"/>
105
106 <!-- Checks for Size Violations. -->
107 <!-- See http://checkstyle.sf.net/config_sizes.html -->
108 <module name="MethodLength"/>
109 <module name="ParameterNumber">
110 <!--<property name="max" value="7"/>-->
111 <property name="max" value="10"/>
112 </module>
113
114 <!-- Checks for whitespace -->
115 <!-- See http://checkstyle.sf.net/config_whitespace.html -->
116 <module name="EmptyForIteratorPad"/>
117 <module name="GenericWhitespace"/>
118 <module name="MethodParamPad"/>
119 <module name="NoWhitespaceAfter"/>
120 <module name="NoWhitespaceBefore"/>
121 <module name="OperatorWrap"/>
122 <module name="ParenPad"/>
123 <module name="TypecastParenPad"/>
124 <module name="WhitespaceAfter">
125 <property name="tokens" value="COMMA, SEMI"/>
126 </module>
127 <module name="WhitespaceAround"/>
128
129 <!-- Modifier Checks -->
130 <!-- See http://checkstyle.sf.net/config_modifiers.html -->
131 <module name="ModifierOrder"/>
132 <module name="RedundantModifier"/>
133
134 <!-- Checks for blocks. You know, those {}'s -->
135 <!-- See http://checkstyle.sf.net/config_blocks.html -->
136 <module name="AvoidNestedBlocks"/>
137 <module name="EmptyBlock"/>
138 <module name="LeftCurly"/>
139 <module name="NeedBraces"/>
140 <module name="RightCurly"/>
141
142 <!-- Checks for common coding problems -->
143 <!-- See http://checkstyle.sf.net/config_coding.html -->
144 <module name="AvoidInlineConditionals"/>
145 <module name="EmptyStatement"/>
146 <module name="EqualsHashCode"/>
147 <module name="HiddenField">
148 <property name="ignoreSetter" value="true"/>
149 <property name="ignoreConstructorParameter" value="true"/>
150 <property name="setterCanReturnItsClass" value="true"/>
151 </module>
152 <module name="IllegalInstantiation"/>
153 <module name="InnerAssignment"/>
154 <module name="MagicNumber"/>
155 <module name="MissingSwitchDefault"/>
156 <module name="SimplifyBooleanExpression"/>
157 <module name="SimplifyBooleanReturn"/>
158
159 <!-- Checks for class design -->
160 <!-- See http://checkstyle.sf.net/config_design.html -->
161 <!--<module name="DesignForExtension"/>-->
162 <module name="FinalClass"/>
163 <module name="HideUtilityClassConstructor"/>
164 <module name="InterfaceIsType"/>
165 <module name="VisibilityModifier"/>
166
167 <!-- Miscellaneous other checks. -->
168 <!-- See http://checkstyle.sf.net/config_misc.html -->
169 <module name="ArrayTypeStyle"/>
170 <module name="FinalParameters"/>
171 <module name="TodoComment"/>
172 <module name="UpperEll"/>
173
174 </module>
175
176 </module>
+0
-510
jdbc/COPYING_LGPL less more
0
1 GNU LESSER GENERAL PUBLIC LICENSE
2 Version 2.1, February 1999
3
4 Copyright (C) 1991, 1999 Free Software Foundation, Inc.
5 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
6 Everyone is permitted to copy and distribute verbatim copies
7 of this license document, but changing it is not allowed.
8
9 [This is the first released version of the Lesser GPL. It also counts
10 as the successor of the GNU Library Public License, version 2, hence
11 the version number 2.1.]
12
13 Preamble
14
15 The licenses for most software are designed to take away your
16 freedom to share and change it. By contrast, the GNU General Public
17 Licenses are intended to guarantee your freedom to share and change
18 free software--to make sure the software is free for all its users.
19
20 This license, the Lesser General Public License, applies to some
21 specially designated software packages--typically libraries--of the
22 Free Software Foundation and other authors who decide to use it. You
23 can use it too, but we suggest you first think carefully about whether
24 this license or the ordinary General Public License is the better
25 strategy to use in any particular case, based on the explanations
26 below.
27
28 When we speak of free software, we are referring to freedom of use,
29 not price. Our General Public Licenses are designed to make sure that
30 you have the freedom to distribute copies of free software (and charge
31 for this service if you wish); that you receive source code or can get
32 it if you want it; that you can change the software and use pieces of
33 it in new free programs; and that you are informed that you can do
34 these things.
35
36 To protect your rights, we need to make restrictions that forbid
37 distributors to deny you these rights or to ask you to surrender these
38 rights. These restrictions translate to certain responsibilities for
39 you if you distribute copies of the library or if you modify it.
40
41 For example, if you distribute copies of the library, whether gratis
42 or for a fee, you must give the recipients all the rights that we gave
43 you. You must make sure that they, too, receive or can get the source
44 code. If you link other code with the library, you must provide
45 complete object files to the recipients, so that they can relink them
46 with the library after making changes to the library and recompiling
47 it. And you must show them these terms so they know their rights.
48
49 We protect your rights with a two-step method: (1) we copyright the
50 library, and (2) we offer you this license, which gives you legal
51 permission to copy, distribute and/or modify the library.
52
53 To protect each distributor, we want to make it very clear that
54 there is no warranty for the free library. Also, if the library is
55 modified by someone else and passed on, the recipients should know
56 that what they have is not the original version, so that the original
57 author's reputation will not be affected by problems that might be
58 introduced by others.
59
60 Finally, software patents pose a constant threat to the existence of
61 any free program. We wish to make sure that a company cannot
62 effectively restrict the users of a free program by obtaining a
63 restrictive license from a patent holder. Therefore, we insist that
64 any patent license obtained for a version of the library must be
65 consistent with the full freedom of use specified in this license.
66
67 Most GNU software, including some libraries, is covered by the
68 ordinary GNU General Public License. This license, the GNU Lesser
69 General Public License, applies to certain designated libraries, and
70 is quite different from the ordinary General Public License. We use
71 this license for certain libraries in order to permit linking those
72 libraries into non-free programs.
73
74 When a program is linked with a library, whether statically or using
75 a shared library, the combination of the two is legally speaking a
76 combined work, a derivative of the original library. The ordinary
77 General Public License therefore permits such linking only if the
78 entire combination fits its criteria of freedom. The Lesser General
79 Public License permits more lax criteria for linking other code with
80 the library.
81
82 We call this license the "Lesser" General Public License because it
83 does Less to protect the user's freedom than the ordinary General
84 Public License. It also provides other free software developers Less
85 of an advantage over competing non-free programs. These disadvantages
86 are the reason we use the ordinary General Public License for many
87 libraries. However, the Lesser license provides advantages in certain
88 special circumstances.
89
90 For example, on rare occasions, there may be a special need to
91 encourage the widest possible use of a certain library, so that it
92 becomes a de-facto standard. To achieve this, non-free programs must
93 be allowed to use the library. A more frequent case is that a free
94 library does the same job as widely used non-free libraries. In this
95 case, there is little to gain by limiting the free library to free
96 software only, so we use the Lesser General Public License.
97
98 In other cases, permission to use a particular library in non-free
99 programs enables a greater number of people to use a large body of
100 free software. For example, permission to use the GNU C Library in
101 non-free programs enables many more people to use the whole GNU
102 operating system, as well as its variant, the GNU/Linux operating
103 system.
104
105 Although the Lesser General Public License is Less protective of the
106 users' freedom, it does ensure that the user of a program that is
107 linked with the Library has the freedom and the wherewithal to run
108 that program using a modified version of the Library.
109
110 The precise terms and conditions for copying, distribution and
111 modification follow. Pay close attention to the difference between a
112 "work based on the library" and a "work that uses the library". The
113 former contains code derived from the library, whereas the latter must
114 be combined with the library in order to run.
115
116 GNU LESSER GENERAL PUBLIC LICENSE
117 TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
118
119 0. This License Agreement applies to any software library or other
120 program which contains a notice placed by the copyright holder or
121 other authorized party saying it may be distributed under the terms of
122 this Lesser General Public License (also called "this License").
123 Each licensee is addressed as "you".
124
125 A "library" means a collection of software functions and/or data
126 prepared so as to be conveniently linked with application programs
127 (which use some of those functions and data) to form executables.
128
129 The "Library", below, refers to any such software library or work
130 which has been distributed under these terms. A "work based on the
131 Library" means either the Library or any derivative work under
132 copyright law: that is to say, a work containing the Library or a
133 portion of it, either verbatim or with modifications and/or translated
134 straightforwardly into another language. (Hereinafter, translation is
135 included without limitation in the term "modification".)
136
137 "Source code" for a work means the preferred form of the work for
138 making modifications to it. For a library, complete source code means
139 all the source code for all modules it contains, plus any associated
140 interface definition files, plus the scripts used to control
141 compilation and installation of the library.
142
143 Activities other than copying, distribution and modification are not
144 covered by this License; they are outside its scope. The act of
145 running a program using the Library is not restricted, and output from
146 such a program is covered only if its contents constitute a work based
147 on the Library (independent of the use of the Library in a tool for
148 writing it). Whether that is true depends on what the Library does
149 and what the program that uses the Library does.
150
151 1. You may copy and distribute verbatim copies of the Library's
152 complete source code as you receive it, in any medium, provided that
153 you conspicuously and appropriately publish on each copy an
154 appropriate copyright notice and disclaimer of warranty; keep intact
155 all the notices that refer to this License and to the absence of any
156 warranty; and distribute a copy of this License along with the
157 Library.
158
159 You may charge a fee for the physical act of transferring a copy,
160 and you may at your option offer warranty protection in exchange for a
161 fee.
162
163 2. You may modify your copy or copies of the Library or any portion
164 of it, thus forming a work based on the Library, and copy and
165 distribute such modifications or work under the terms of Section 1
166 above, provided that you also meet all of these conditions:
167
168 a) The modified work must itself be a software library.
169
170 b) You must cause the files modified to carry prominent notices
171 stating that you changed the files and the date of any change.
172
173 c) You must cause the whole of the work to be licensed at no
174 charge to all third parties under the terms of this License.
175
176 d) If a facility in the modified Library refers to a function or a
177 table of data to be supplied by an application program that uses
178 the facility, other than as an argument passed when the facility
179 is invoked, then you must make a good faith effort to ensure that,
180 in the event an application does not supply such function or
181 table, the facility still operates, and performs whatever part of
182 its purpose remains meaningful.
183
184 (For example, a function in a library to compute square roots has
185 a purpose that is entirely well-defined independent of the
186 application. Therefore, Subsection 2d requires that any
187 application-supplied function or table used by this function must
188 be optional: if the application does not supply it, the square
189 root function must still compute square roots.)
190
191 These requirements apply to the modified work as a whole. If
192 identifiable sections of that work are not derived from the Library,
193 and can be reasonably considered independent and separate works in
194 themselves, then this License, and its terms, do not apply to those
195 sections when you distribute them as separate works. But when you
196 distribute the same sections as part of a whole which is a work based
197 on the Library, the distribution of the whole must be on the terms of
198 this License, whose permissions for other licensees extend to the
199 entire whole, and thus to each and every part regardless of who wrote
200 it.
201
202 Thus, it is not the intent of this section to claim rights or contest
203 your rights to work written entirely by you; rather, the intent is to
204 exercise the right to control the distribution of derivative or
205 collective works based on the Library.
206
207 In addition, mere aggregation of another work not based on the Library
208 with the Library (or with a work based on the Library) on a volume of
209 a storage or distribution medium does not bring the other work under
210 the scope of this License.
211
212 3. You may opt to apply the terms of the ordinary GNU General Public
213 License instead of this License to a given copy of the Library. To do
214 this, you must alter all the notices that refer to this License, so
215 that they refer to the ordinary GNU General Public License, version 2,
216 instead of to this License. (If a newer version than version 2 of the
217 ordinary GNU General Public License has appeared, then you can specify
218 that version instead if you wish.) Do not make any other change in
219 these notices.
220
221 Once this change is made in a given copy, it is irreversible for
222 that copy, so the ordinary GNU General Public License applies to all
223 subsequent copies and derivative works made from that copy.
224
225 This option is useful when you wish to copy part of the code of
226 the Library into a program that is not a library.
227
228 4. You may copy and distribute the Library (or a portion or
229 derivative of it, under Section 2) in object code or executable form
230 under the terms of Sections 1 and 2 above provided that you accompany
231 it with the complete corresponding machine-readable source code, which
232 must be distributed under the terms of Sections 1 and 2 above on a
233 medium customarily used for software interchange.
234
235 If distribution of object code is made by offering access to copy
236 from a designated place, then offering equivalent access to copy the
237 source code from the same place satisfies the requirement to
238 distribute the source code, even though third parties are not
239 compelled to copy the source along with the object code.
240
241 5. A program that contains no derivative of any portion of the
242 Library, but is designed to work with the Library by being compiled or
243 linked with it, is called a "work that uses the Library". Such a
244 work, in isolation, is not a derivative work of the Library, and
245 therefore falls outside the scope of this License.
246
247 However, linking a "work that uses the Library" with the Library
248 creates an executable that is a derivative of the Library (because it
249 contains portions of the Library), rather than a "work that uses the
250 library". The executable is therefore covered by this License.
251 Section 6 states terms for distribution of such executables.
252
253 When a "work that uses the Library" uses material from a header file
254 that is part of the Library, the object code for the work may be a
255 derivative work of the Library even though the source code is not.
256 Whether this is true is especially significant if the work can be
257 linked without the Library, or if the work is itself a library. The
258 threshold for this to be true is not precisely defined by law.
259
260 If such an object file uses only numerical parameters, data
261 structure layouts and accessors, and small macros and small inline
262 functions (ten lines or less in length), then the use of the object
263 file is unrestricted, regardless of whether it is legally a derivative
264 work. (Executables containing this object code plus portions of the
265 Library will still fall under Section 6.)
266
267 Otherwise, if the work is a derivative of the Library, you may
268 distribute the object code for the work under the terms of Section 6.
269 Any executables containing that work also fall under Section 6,
270 whether or not they are linked directly with the Library itself.
271
272 6. As an exception to the Sections above, you may also combine or
273 link a "work that uses the Library" with the Library to produce a
274 work containing portions of the Library, and distribute that work
275 under terms of your choice, provided that the terms permit
276 modification of the work for the customer's own use and reverse
277 engineering for debugging such modifications.
278
279 You must give prominent notice with each copy of the work that the
280 Library is used in it and that the Library and its use are covered by
281 this License. You must supply a copy of this License. If the work
282 during execution displays copyright notices, you must include the
283 copyright notice for the Library among them, as well as a reference
284 directing the user to the copy of this License. Also, you must do one
285 of these things:
286
287 a) Accompany the work with the complete corresponding
288 machine-readable source code for the Library including whatever
289 changes were used in the work (which must be distributed under
290 Sections 1 and 2 above); and, if the work is an executable linked
291 with the Library, with the complete machine-readable "work that
292 uses the Library", as object code and/or source code, so that the
293 user can modify the Library and then relink to produce a modified
294 executable containing the modified Library. (It is understood
295 that the user who changes the contents of definitions files in the
296 Library will not necessarily be able to recompile the application
297 to use the modified definitions.)
298
299 b) Use a suitable shared library mechanism for linking with the
300 Library. A suitable mechanism is one that (1) uses at run time a
301 copy of the library already present on the user's computer system,
302 rather than copying library functions into the executable, and (2)
303 will operate properly with a modified version of the library, if
304 the user installs one, as long as the modified version is
305 interface-compatible with the version that the work was made with.
306
307 c) Accompany the work with a written offer, valid for at least
308 three years, to give the same user the materials specified in
309 Subsection 6a, above, for a charge no more than the cost of
310 performing this distribution.
311
312 d) If distribution of the work is made by offering access to copy
313 from a designated place, offer equivalent access to copy the above
314 specified materials from the same place.
315
316 e) Verify that the user has already received a copy of these
317 materials or that you have already sent this user a copy.
318
319 For an executable, the required form of the "work that uses the
320 Library" must include any data and utility programs needed for
321 reproducing the executable from it. However, as a special exception,
322 the materials to be distributed need not include anything that is
323 normally distributed (in either source or binary form) with the major
324 components (compiler, kernel, and so on) of the operating system on
325 which the executable runs, unless that component itself accompanies
326 the executable.
327
328 It may happen that this requirement contradicts the license
329 restrictions of other proprietary libraries that do not normally
330 accompany the operating system. Such a contradiction means you cannot
331 use both them and the Library together in an executable that you
332 distribute.
333
334 7. You may place library facilities that are a work based on the
335 Library side-by-side in a single library together with other library
336 facilities not covered by this License, and distribute such a combined
337 library, provided that the separate distribution of the work based on
338 the Library and of the other library facilities is otherwise
339 permitted, and provided that you do these two things:
340
341 a) Accompany the combined library with a copy of the same work
342 based on the Library, uncombined with any other library
343 facilities. This must be distributed under the terms of the
344 Sections above.
345
346 b) Give prominent notice with the combined library of the fact
347 that part of it is a work based on the Library, and explaining
348 where to find the accompanying uncombined form of the same work.
349
350 8. You may not copy, modify, sublicense, link with, or distribute
351 the Library except as expressly provided under this License. Any
352 attempt otherwise to copy, modify, sublicense, link with, or
353 distribute the Library is void, and will automatically terminate your
354 rights under this License. However, parties who have received copies,
355 or rights, from you under this License will not have their licenses
356 terminated so long as such parties remain in full compliance.
357
358 9. You are not required to accept this License, since you have not
359 signed it. However, nothing else grants you permission to modify or
360 distribute the Library or its derivative works. These actions are
361 prohibited by law if you do not accept this License. Therefore, by
362 modifying or distributing the Library (or any work based on the
363 Library), you indicate your acceptance of this License to do so, and
364 all its terms and conditions for copying, distributing or modifying
365 the Library or works based on it.
366
367 10. Each time you redistribute the Library (or any work based on the
368 Library), the recipient automatically receives a license from the
369 original licensor to copy, distribute, link with or modify the Library
370 subject to these terms and conditions. You may not impose any further
371 restrictions on the recipients' exercise of the rights granted herein.
372 You are not responsible for enforcing compliance by third parties with
373 this License.
374
375 11. If, as a consequence of a court judgment or allegation of patent
376 infringement or for any other reason (not limited to patent issues),
377 conditions are imposed on you (whether by court order, agreement or
378 otherwise) that contradict the conditions of this License, they do not
379 excuse you from the conditions of this License. If you cannot
380 distribute so as to satisfy simultaneously your obligations under this
381 License and any other pertinent obligations, then as a consequence you
382 may not distribute the Library at all. For example, if a patent
383 license would not permit royalty-free redistribution of the Library by
384 all those who receive copies directly or indirectly through you, then
385 the only way you could satisfy both it and this License would be to
386 refrain entirely from distribution of the Library.
387
388 If any portion of this section is held invalid or unenforceable under
389 any particular circumstance, the balance of the section is intended to
390 apply, and the section as a whole is intended to apply in other
391 circumstances.
392
393 It is not the purpose of this section to induce you to infringe any
394 patents or other property right claims or to contest validity of any
395 such claims; this section has the sole purpose of protecting the
396 integrity of the free software distribution system which is
397 implemented by public license practices. Many people have made
398 generous contributions to the wide range of software distributed
399 through that system in reliance on consistent application of that
400 system; it is up to the author/donor to decide if he or she is willing
401 to distribute software through any other system and a licensee cannot
402 impose that choice.
403
404 This section is intended to make thoroughly clear what is believed to
405 be a consequence of the rest of this License.
406
407 12. If the distribution and/or use of the Library is restricted in
408 certain countries either by patents or by copyrighted interfaces, the
409 original copyright holder who places the Library under this License
410 may add an explicit geographical distribution limitation excluding those
411 countries, so that distribution is permitted only in or among
412 countries not thus excluded. In such case, this License incorporates
413 the limitation as if written in the body of this License.
414
415 13. The Free Software Foundation may publish revised and/or new
416 versions of the Lesser General Public License from time to time.
417 Such new versions will be similar in spirit to the present version,
418 but may differ in detail to address new problems or concerns.
419
420 Each version is given a distinguishing version number. If the Library
421 specifies a version number of this License which applies to it and
422 "any later version", you have the option of following the terms and
423 conditions either of that version or of any later version published by
424 the Free Software Foundation. If the Library does not specify a
425 license version number, you may choose any version ever published by
426 the Free Software Foundation.
427
428 14. If you wish to incorporate parts of the Library into other free
429 programs whose distribution conditions are incompatible with these,
430 write to the author to ask for permission. For software which is
431 copyrighted by the Free Software Foundation, write to the Free
432 Software Foundation; we sometimes make exceptions for this. Our
433 decision will be guided by the two goals of preserving the free status
434 of all derivatives of our free software and of promoting the sharing
435 and reuse of software generally.
436
437 NO WARRANTY
438
439 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
440 WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
441 EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
442 OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
443 KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
444 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
445 PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
446 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
447 THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
448
449 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
450 WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
451 AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
452 FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
453 CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
454 LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
455 RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
456 FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
457 SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
458 DAMAGES.
459
460 END OF TERMS AND CONDITIONS
461
462 How to Apply These Terms to Your New Libraries
463
464 If you develop a new library, and you want it to be of the greatest
465 possible use to the public, we recommend making it free software that
466 everyone can redistribute and change. You can do so by permitting
467 redistribution under these terms (or, alternatively, under the terms
468 of the ordinary General Public License).
469
470 To apply these terms, attach the following notices to the library.
471 It is safest to attach them to the start of each source file to most
472 effectively convey the exclusion of warranty; and each file should
473 have at least the "copyright" line and a pointer to where the full
474 notice is found.
475
476
477 <one line to give the library's name and a brief idea of what it does.>
478 Copyright (C) <year> <name of author>
479
480 This library is free software; you can redistribute it and/or
481 modify it under the terms of the GNU Lesser General Public
482 License as published by the Free Software Foundation; either
483 version 2.1 of the License, or (at your option) any later version.
484
485 This library is distributed in the hope that it will be useful,
486 but WITHOUT ANY WARRANTY; without even the implied warranty of
487 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
488 Lesser General Public License for more details.
489
490 You should have received a copy of the GNU Lesser General Public
491 License along with this library; if not, write to the Free Software
492 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
493
494 Also add information on how to contact you by electronic and paper mail.
495
496 You should also get your employer (if you work as a programmer) or
497 your school, if any, to sign a "copyright disclaimer" for the library,
498 if necessary. Here is a sample; alter the names:
499
500 Yoyodyne, Inc., hereby disclaims all copyright interest in the
501 library `Frob' (a library for tweaking knobs) written by James
502 Random Hacker.
503
504 <signature of Ty Coon>, 1 April 1990
505 Ty Coon, President of Vice
506
507 That's all there is to it!
508
509
+0
-236
jdbc/README less more
0
1 *** PostGIS JDBC Driver extension README / FAQ ***
2
3 (C) 2005 Markus Schaber <markus.schaber@logix-tt.com>
4
5
6 * What is it all about? *
7
8 JDBC is an database driver specification for Java. Like ODBC in the C
9 world, JDBC allows java applications to transparently use different
10 JDBC compliant databases without any source code changes. PostgreSQL,
11 the database PostGIS is written for, comes with a driver that
12 follows this specification. For downloads and more info, see:
13 http://jdbc.postgresql.org/download.html
14
15 The purpose of the JDBC Driver extension is to give the PostgreSQL
16 JDBC driver some understanding of the PostGIS data types (Geometry,
17 Box3D, Box2D). Without this, the Application can only get byte arrays
18 or strings (binary and text representation, rsp.) and has to parse it
19 on its own. When registering this extension, the Application can
20 simply call getObject(column) on the result of the query, and get a
21 real java object that is modeled after the OpenGIS spec. It also can
22 create or modify this objects itsself and then pass them into the
23 database via the PreparedStatement.setObject() method.
24
25 Currently, the code is tested with PostGIS 0.8.1, 0.9.1. 0.9.2 and
26 1.0.0. It supports both the new hex-encoded EWKB canonical text
27 representation used by PostGIS 1.0.0 lwgeom code, and the old, less
28 efficient WKT like representation used by previous releases when
29 reading data from the server. When sending data to the server, it
30 currently always uses the latter form, which is compatible to all
31 PostGIS versions.
32
33
34 * Do I need it? *
35
36 If you happen to write GIS applications, you can propably benefit.
37
38 In case your applications are PostGIS specific, you can fully exploit
39 the functionality, see "How to I use it" below for instructions and
40 the src/examples directory for some code examples.
41
42 If you rather prefer to stay OpenGIS compliant, then you cannot use
43 the full driver embedding, as this is PostGIS specific functionality.
44 But you can still use the geometry classes as a lightweight java
45 geometry model if you do not want to use a full-blown GIS
46 implementation like jts. Simply use the asText() and
47 GeometryFromText() OpenGIS SQL functions against whichever OpenGIS
48 compliant server you want, and use the WKT parsing constructors or
49 PGgeometry.geomFromString() as well as Geometry.toString() to convert
50 between WKT strings and geometry objects.
51
52
53 * Is it free? *
54
55 Yes. The actual Driver extension code is licensed under the GNU LGPL,
56 this allows everyone to include the code in his projects. You do not
57 have to pay any license fees, and you can keep your own application
58 code proprietary, but you have to make the PostGIS source code available
59 to any receivers, including any modifications you apply to it. For
60 details, please see the license file COPYING_LGPL.
61
62 The Build files and examples are licensed under GNU GPL, just like the
63 rest of PostGIS is. This is not LGPL as applications usually do not
64 link against those.
65
66
67 * How do I build it? *
68
69 There are older make files with which you can try to build, but maven is recommended,
70 as it handles dependencies on a better and cleaner way.
71
72 You have to install maven on your computer to build it. To install maven you can try
73 to search on your software repositories or read the documentation:
74 http://maven.apache.org/download.html
75
76 To compile your postgis driver, go to the jdbc folder and execute the console
77 command "mvn package". This should create a postgis jar on the target folder
78 inside the jdbc folder.
79
80 Note that your postgis driver version does not constrain the PostgreSQL
81 server version. As the JDBC drivers are downwards compatible against older
82 servers, and PostgreSQL servers typically accept older clients, you can
83 easily use e. G. a pgjdbc 8.0 against a PostgreSQL 7.3 server. To benefit
84 from optimizations and bugfixes, it is generally suggested to use the
85 newest stable pgjdbc build that is documented to work against your
86 server release.
87
88 * It is called jdbc2 - does it work with jdbc3, too? *
89
90 To make it short: The naming does not refer to SUN jdbc standard releases
91 jdbc-1, jdbc-2 or jdbc-3.
92
93 The current naming is somehow unfortunate. The directory simply is named
94 jdbc2 because it is the successor of Paul Ramsey's original jdbc directory,
95 which used to exist parallel in the CVS repository. As CVS does its best
96 to hinder useful version tracking across file renames, the name was kept
97 even after removal of the original jdbc subproject.
98
99 Please note that the PostgreSQL JDBC driver itsself is released in
100 several flavours for different JDBC relases and sun JDK releases, but
101 currently, the same postgis.jar should work with all of them. If not,
102 you clearly found a bug, and we kindly ask you to report it.
103
104 If you run into troubles, make shure that you use the newest pgjdbc build.
105 Especially pre releases are known to contain bugs (that's why they are pre
106 releases), and e. G. 8.0 build 309 contained some problems that are fixed
107 in 8.0 build 313.
108
109
110 * How do I use it? *
111
112 To use the PostGIS types, you need the postgis.jar and the pgjdbc
113 driver in your classpath.
114
115 The PostGIS extension must be registered within the JDBC driver.
116 There are three ways to do this:
117
118 - If you use pgjdbc 8.0, the org/postgresql/driverconfig.properties
119 file contained in the postgis.jar autoregisters the PostGIS
120 extension for the PostGIS data types (geometry, box2d, box3d)
121 within the pgjdbc driver.
122
123 - You can use the org.postgis.DriverWrapper as replacement for the
124 jdbc driver. This class wraps the PostGreSQL Driver to
125 transparently add the PostGIS Object Classes. This method currently
126 works both with J2EE DataSources, and with the older DriverManager
127 framework. I's a thin wrapper around org.postgresql.Driver that
128 simply registers the extension on every new connection created.
129
130 To use it, you replace the "jdbc:postgresql:" with a
131 "jdbc:postgresql_postGIS" in the jdbc URL, and make your
132 environment aware of the new Driver class.
133
134 DriverManager users simply register org/postgis/DriverWrapper
135 instead of (or in addition to) org.postgresql.Driver, see
136 examples/TestBoxes.connect() for an working code.
137
138 DataSource users similarly have to configure their datasource to
139 use the different class. The following works for jboss, put it in
140 your-ds.xml: <driver-class>org.postgis.DriverWrapper</driver-class>
141
142 - Of course, you can also manually register the Datatypes on your
143 pgjdbc connection. You have to cast your connection to PGConnection
144 and then call:
145
146 pgconn.addDataType("geometry", "org.postgis.PGgeometry");
147 pgconn.addDataType("box3d", "org.postgis.PGbox3d");
148 pgconn.addDataType("box2d", "org.postgis.PGbox2d");
149
150 You may need to dig through some wrappers when running in an
151 appserver. E. G. for JBoss, The datasource actually gives you a
152 instance of org.jboss.resource.adapter.jdbc.WrappedConnection and
153 have to call getUnderlyingConnection() on it to get the
154 PGConnection instance.)
155
156 Also note that the above addDataType() methods known from earlier
157 pgjdbc versions are deprecated in pgjdbc 8.0 (but still work), see
158 the commented code variants in the DriverWrapper.addGisTypes()
159 method for an alternative.
160
161 Note: Even using pgjdbc 8.0, you may still want to use the second or
162 third approach if you have several pgjdbc extensions that
163 autoregister for the same PostGIS types, as the driver cannot guess
164 which extension it should actually use on which connection. The
165 current pgjdbc implementation simply parses all
166 org/postgresql/driverconfig.properties the classloader can find in his
167 classpath, using the first definition found for each type.
168
169
170 * How to I run the tests? Are they allowed to fail? *
171
172 There are two types of tests provided, offline and online. Offline
173 tests can run without a PostGIS server, the online tests need a
174 PostGIS server to connect to.
175
176 - Offline Tests
177
178 The easiest way to run the offline tests is "make offlinetests".
179
180 The offline tests should always complete without any failure. If
181 you happen to get a failure here, it is a bug in the PostGIS code
182 (or, very unlikely, in the JDK/JRE or Hardware you use). Please
183 contact the PostGIS developer list in this case.
184
185 - Online tests
186
187 The online tests can be ran with "make onlinetests", but they need
188 a specially prepared database to connect against, and the pgjdbc
189 driver available in your classpath. The Makefile provides defaults
190 for PGHOST, PGPOR, PGDATABASE, PGUSER and PGPASS, you can override
191 them for your needs. For the jtest, the user needs to create and
192 drop table privileges, the two other tests do not use any table.
193 Make shure you have the PostGIS installed in the database.
194
195 None of the online tests should report any failure. However, some of the
196 tests are skipped against PostGix 0.X servers as 0.8.X and 0.9.X, those
197 are the box2d tests (because this datatype simply is missing on those
198 releases), as well as 22 skipped tests for some geometry representations
199 that those old releases do not support. This is a PostGIS server side
200 problem as the server fails to parse some OpenGIS compliant WKT
201 representations, and structurally (but not geometrically or topologically)
202 mangles some other geometries. They are unlikely to be fixed in those
203 releases as users should migrate to PostGIS 1.0.
204
205 The Autoregister Test needs a pgjdbc version 8.0 or newer, and will
206 simply do nothing with older pgjdbc versions.
207
208 If you get any failure messages in the online tests, check whether
209 your really fulfil the prerequisites above. If yes, please contact
210 the PostGIS developer list.
211
212
213 * What about the JTS stuff *
214
215 There's beta support for the JTS 1.6 geometry implementations instead of the
216 native PostGIS classes on the java client side. Simply add jts_1.6.jar to your
217 CLASSPATH, "make postgis_jts" and use at your own risk.
218
219
220 * How can I contact you? *
221
222 Well, the best place are the official PostGIS mailing lists for PostGIS,
223 subscription information is linked at:
224
225 http://postgis.net/
226
227 If you want to report errors, please try to send us all the details we need
228 to reproduce your problem. A small, self-contained test case would be best.
229
230
231 * Phew. That's all? *
232
233 Yes. For now, at least.
234
235 Happy Coding!
+0
-92
jdbc/pom.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
2 <modelVersion>4.0.0</modelVersion>
3
4 <parent>
5 <groupId>net.postgis</groupId>
6 <artifactId>postgis-java-aggregator</artifactId>
7 <version>2.5.0</version>
8 </parent>
9
10 <artifactId>postgis-jdbc</artifactId>
11 <version>2.5.0</version>
12 <packaging>jar</packaging>
13
14 <name>Postgis JDBC Driver</name>
15 <description>PostGIS adds support for geographic objects to the PostgreSQL object-relational database.</description>
16
17 <properties />
18
19 <dependencies>
20 <dependency>
21 <groupId>net.postgis</groupId>
22 <artifactId>postgis-geometry</artifactId>
23 <version>2.5.0</version>
24 </dependency>
25 <dependency>
26 <groupId>org.postgresql</groupId>
27 <artifactId>postgresql</artifactId>
28 <version>${dependency.postgresql-jdbc.version}</version>
29 </dependency>
30 <dependency>
31 <groupId>net.postgis.tools</groupId>
32 <artifactId>test-utils</artifactId>
33 <version>2.5.0</version>
34 <scope>test</scope>
35 </dependency>
36 </dependencies>
37
38 <build>
39 <resources>
40 <resource>
41 <directory>src/main/resources</directory>
42 <filtering>true</filtering>
43 </resource>
44 </resources>
45 <testResources>
46 <testResource>
47 <directory>src/test/resources</directory>
48 </testResource>
49 <testResource>
50 <directory>src/test/resources-filtered</directory>
51 <filtering>true</filtering>
52 </testResource>
53 </testResources>
54 <plugins>
55 <plugin>
56 <groupId>org.apache.maven.plugins</groupId>
57 <artifactId>maven-failsafe-plugin</artifactId>
58 <executions>
59 <execution>
60 <id>integration-tests</id>
61 <goals>
62 <goal>integration-test</goal>
63 <goal>verify</goal>
64 </goals>
65 <configuration>
66 <skip>${maven.integration.test.skip}</skip>
67 <forkCount>${failsafe.forkCount}</forkCount>
68 <useSystemClassLoader>${failsafe.useSystemClassLoader}</useSystemClassLoader>
69 <suiteXmlFiles>
70 <suiteXmlFile>${project.build.testOutputDirectory}/testng-it.xml</suiteXmlFile>
71 </suiteXmlFiles>
72 </configuration>
73 </execution>
74 </executions>
75 </plugin>
76 <plugin>
77 <groupId>org.apache.maven.plugins</groupId>
78 <artifactId>maven-surefire-plugin</artifactId>
79 <configuration>
80 <skip>${maven.test.skip}</skip>
81 <forkCount>${surefire.forkCount}</forkCount>
82 <useSystemClassLoader>${surefire.useSystemClassLoader}</useSystemClassLoader>
83 <suiteXmlFiles>
84 <suiteXmlFile>${project.build.testOutputDirectory}/testng.xml</suiteXmlFile>
85 </suiteXmlFiles>
86 </configuration>
87 </plugin>
88 </plugins>
89 </build>
90
91 </project>
+0
-183
jdbc/src/main/java/examples/TestAutoregister.java less more
0 /*
1 * TestAutoregister.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - example and test classes
4 *
5 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
6 *
7 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24
25 package examples;
26
27 import org.postgis.PGbox2d;
28 import org.postgis.PGbox3d;
29 import org.postgis.PGgeometry;
30 import org.postgresql.Driver;
31 import org.postgresql.util.PGobject;
32
33 import java.sql.Connection;
34 import java.sql.DriverManager;
35 import java.sql.ResultSet;
36 import java.sql.SQLException;
37 import java.sql.Statement;
38
39 /**
40 * This test program tests whether the autoregistration of PostGIS data types
41 * within the pgjdbc driver was successful. This is supposed to work with
42 * pgjdbc.jar version 8.0 and newer, and thus refuses to work with older pgjdbc
43 * versions. (But it will work fine against older servers.) It also checks for
44 * postgis version to know whether box2d is available.
45 */
46 public class TestAutoregister {
47
48 public static void main(String[] args) {
49 String dburl = null;
50 String dbuser = null;
51 String dbpass = null;
52
53 if (args.length == 3) {
54 System.out.println("Testing proper auto-registration");
55 dburl = args[0];
56 dbuser = args[1];
57 dbpass = args[2];
58 } else {
59 System.err.println("Usage: java examples/TestParser dburl user pass");
60 System.exit(1);
61 // Signal the compiler that code flow ends here.
62 return;
63 }
64
65 System.out.println("Driver version: " + Driver.getVersion());
66 int major;
67 try {
68 major = new Driver().getMajorVersion();
69 } catch (Exception e) {
70 System.err.println("Cannot create Driver instance: " + e.getMessage());
71 System.exit(1);
72 return;
73 }
74
75 if (major < 8) {
76 System.err.println("Your pgdjbc " + major
77 + ".X is too old, it does not support autoregistration!");
78 return;
79 }
80
81 System.out.println("Creating JDBC connection to " + dburl);
82 Connection conn = null;
83 Statement stat = null;
84 try {
85 conn = DriverManager.getConnection(dburl, dbuser, dbpass);
86 stat = conn.createStatement();
87 } catch (SQLException e) {
88 System.err.println("Connection initialization failed, aborting.");
89 e.printStackTrace();
90 System.exit(1);
91 // signal the compiler that code flow ends here:
92 throw new AssertionError();
93 }
94
95 int postgisServerMajor = 0;
96 try {
97 postgisServerMajor = getPostgisMajor(stat);
98 } catch (SQLException e) {
99 System.err.println("Error fetching PostGIS version: " + e.getMessage());
100 System.err.println("Is PostGIS really installed in the database?");
101 System.exit(1);
102 // signal the compiler that code flow ends here:
103 throw new AssertionError();
104 }
105
106 System.out.println("PostGIS Version: " + postgisServerMajor);
107
108 PGobject result = null;
109
110 /* Test geometries */
111 try {
112 ResultSet rs = stat.executeQuery("SELECT 'POINT(1 2)'::geometry");
113 rs.next();
114 result = (PGobject) rs.getObject(1);
115 if (result instanceof PGgeometry) {
116 System.out.println("PGgeometry successful!");
117 } else {
118 System.out.println("PGgeometry failed!");
119 }
120 } catch (SQLException e) {
121 System.err.println("Selecting geometry failed: " + e.getMessage());
122 System.exit(1);
123 // Signal the compiler that code flow ends here.
124 return;
125 }
126
127 /* Test box3d */
128 try {
129 ResultSet rs = stat.executeQuery("SELECT 'BOX3D(1 2 3, 4 5 6)'::box3d");
130 rs.next();
131 result = (PGobject) rs.getObject(1);
132 if (result instanceof PGbox3d) {
133 System.out.println("Box3d successful!");
134 } else {
135 System.out.println("Box3d failed!");
136 }
137 } catch (SQLException e) {
138 System.err.println("Selecting box3d failed: " + e.getMessage());
139 System.exit(1);
140 // Signal the compiler that code flow ends here.
141 return;
142 }
143
144 /* Test box2d if appropriate */
145 if (postgisServerMajor < 1) {
146 System.out.println("PostGIS version is too old, skipping box2ed test");
147 System.err.println("PostGIS version is too old, skipping box2ed test");
148 } else {
149 try {
150 ResultSet rs = stat.executeQuery("SELECT 'BOX(1 2,3 4)'::box2d");
151 rs.next();
152 result = (PGobject) rs.getObject(1);
153 if (result instanceof PGbox2d) {
154 System.out.println("Box2d successful!");
155 } else {
156 System.out.println("Box2d failed! " + result.getClass().getName());
157 }
158 } catch (SQLException e) {
159 System.err.println("Selecting box2d failed: " + e.getMessage());
160 System.exit(1);
161 // Signal the compiler that code flow ends here.
162 return;
163 }
164 }
165
166 System.out.println("Finished.");
167 // If we finished up to here without exitting, we passed all tests.
168 System.err.println("TestAutoregister.java finished without errors.");
169 }
170
171 public static int getPostgisMajor(Statement stat) throws SQLException {
172 ResultSet rs = stat.executeQuery("SELECT postgis_version()");
173 rs.next();
174 String version = rs.getString(1);
175 if (version == null) {
176 throw new SQLException("postgis_version returned NULL!");
177 }
178 version = version.trim();
179 int idx = version.indexOf('.');
180 return Integer.parseInt(version.substring(0, idx));
181 }
182 }
+0
-403
jdbc/src/main/java/org/postgis/DriverWrapper.java less more
0 /*
1 * This library is free software; you can redistribute it and/or
2 * modify it under the terms of the GNU Lesser General Public
3 * License as published by the Free Software Foundation; either
4 * version 2.1 of the License, or (at your option) any later version.
5 *
6 * This library is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 * Lesser General Public License for more details.
10 *
11 * You should have received a copy of the GNU Lesser General Public
12 * License along with this library; if not, write to the Free Software
13 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
14 *
15 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
16 *
17 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
18 */
19
20 package org.postgis;
21
22
23 import java.sql.Connection;
24 import java.sql.SQLException;
25 import java.util.Properties;
26 import java.util.logging.Level;
27 import java.util.logging.Logger;
28
29 import org.postgresql.Driver;
30 import org.postgresql.PGConnection;
31
32
33 /**
34 * DriverWrapper
35 *
36 * Wraps the PostGreSQL Driver to transparently add the PostGIS Object Classes.
37 * This avoids the need of explicit addDataType() calls from the driver users
38 * side.
39 *
40 * This method currently works with J2EE DataSource implementations, and with
41 * DriverManager framework.
42 *
43 * Simply replace the "jdbc:postgresql:" with a "jdbc:postgresql_postGIS:" in
44 * the jdbc URL.
45 *
46 * When using the drivermanager, you need to initialize DriverWrapper instead of
47 * (or in addition to) org.postgresql.Driver. When using a J2EE DataSource
48 * implementation, set the driver class property in the datasource config, the
49 * following works for jboss:
50 *
51 * <code>
52 * &lt;driver-class&gt;org.postgis.DriverWrapper&lt;/driver-class&gt;
53 * </code>
54 * If you don't like or want to use the DriverWrapper, you have two
55 * alternatives, see the README file.
56 *
57 * Also note that the addDataType() methods known from earlier pgjdbc versions
58 * are deprecated in pgjdbc 8.0, see the commented code variants in the
59 * addGisTypes() method.
60 *
61 * This wrapper always uses EWKT as canonical text representation, and thus
62 * works against PostGIS 1.x servers as well as 0.x (tested with 0.8, 0.9 and
63 * 1.0).
64 *
65 * @author {@literal Markus Schaber <markus.schaber@logix-tt.com>}
66 * @see DriverWrapperLW
67 * @see DriverWrapperAutoprobe
68 */
69 public class DriverWrapper extends Driver {
70
71 /** The static logger instance. */
72 protected static final Logger logger = Logger.getLogger("org.postgis.DriverWrapper");
73
74 public static final String POSTGRES_PROTOCOL = "jdbc:postgresql:";
75 public static final String POSTGIS_PROTOCOL = "jdbc:postgresql_postGIS:";
76 public static final String REVISION = "$Revision$";
77 protected static TypesAdder ta72 = null;
78 protected static TypesAdder ta74 = null;
79 protected static TypesAdder ta80 = null;
80
81 protected TypesAdder typesAdder;
82
83
84 static {
85 try {
86 // Try to register ourself to the DriverManager
87 java.sql.DriverManager.registerDriver(new DriverWrapper());
88 } catch (SQLException e) {
89 logger.log(Level.WARNING, "Error registering PostGIS Wrapper Driver", e);
90 }
91 }
92
93
94 /**
95 * Default constructor.
96 *
97 * This also loads the appropriate TypesAdder for our SQL Driver instance.
98 *
99 * @throws SQLException when a SQLException occurs
100 */
101 public DriverWrapper() throws SQLException {
102 super();
103 typesAdder = getTypesAdder(this);
104 // The debug method is @since 7.2
105 if (super.getMajorVersion() > 8 || super.getMinorVersion() > 1) {
106 logger.fine(this.getClass().getName() + " loaded TypesAdder: "
107 + typesAdder.getClass().getName());
108 }
109 }
110
111
112 protected static TypesAdder getTypesAdder(final Driver d) throws SQLException {
113 if (d.getMajorVersion() == 7) {
114 if (d.getMinorVersion() >= 3) {
115 if (ta74 == null) {
116 ta74 = loadTypesAdder("74");
117 }
118 return ta74;
119 } else {
120 if (ta72 == null) {
121 ta72 = loadTypesAdder("72");
122 }
123 return ta72;
124 }
125 } else {
126 if (ta80 == null) {
127 ta80 = loadTypesAdder("80");
128 }
129 return ta80;
130 }
131 }
132
133
134 private static TypesAdder loadTypesAdder(final String version) throws SQLException {
135 try {
136 Class klass = Class.forName("org.postgis.DriverWrapper$TypesAdder" + version);
137 return (TypesAdder) klass.newInstance();
138 } catch (Exception e) {
139 throw new SQLException("Cannot create TypesAdder instance! " + e.getMessage());
140 }
141 }
142
143
144 /**
145 * Creates a postgresql connection, and then adds the PostGIS data types to it calling addpgtypes().
146 *
147 * A side-effect of this method is that the specified url parameter may be be changed
148 *
149 * @param url the URL of the database to connect to (may be changed as a side-effect of this method)
150 * @param info a list of arbitrary tag/value pairs as connection arguments
151 * @return a connection to the URL or null if it isnt us
152 * @exception SQLException if a database access error occurs
153 *
154 * @see java.sql.Driver#connect
155 * @see org.postgresql.Driver
156 */
157 public java.sql.Connection connect(String url, final Properties info) throws SQLException {
158 url = mangleURL(url);
159 Connection result = super.connect(url, info);
160 typesAdder.addGT(result, useLW(result));
161 return result;
162 }
163
164
165 /**
166 * Do we have HexWKB as well known text representation - to be overridden by
167 * subclasses.
168 *
169 * @param result Connection to check
170 * @return true if using EWKB, false otherwise
171 */
172 protected boolean useLW(final Connection result) {
173 if (result == null) {
174 throw new IllegalArgumentException("null is no valid parameter");
175 }
176 return false;
177 }
178
179
180 /**
181 * Check whether the driver thinks he can handle the given URL.
182 *
183 * A side-effect of this method is that the specified url parameter may be be changed
184 *
185 * @see java.sql.Driver#acceptsURL
186 * @param url the URL of the driver (may be changed as a side-effect of this method)
187 * @return true if this driver accepts the given URL
188 */
189 public boolean acceptsURL(String url) {
190 try {
191 url = mangleURL(url);
192 } catch (SQLException e) {
193 return false;
194 }
195 return super.acceptsURL(url);
196 }
197
198
199 /**
200 * Returns our own CVS version plus postgres Version
201 *
202 * @return String value reprenstation of the version
203 */
204 public static String getVersion() {
205 return "PostGisWrapper " + REVISION + ", wrapping " + Driver.getVersion();
206 }
207
208
209 /*
210 * Here follows the addGISTypes() stuff. This is a little tricky because the
211 * pgjdbc people had several, partially incompatible API changes during 7.2
212 * and 8.0. We still want to support all those releases, however.
213 *
214 */
215 /**
216 * adds the JTS/PostGIS Data types to a PG 7.3+ Connection. If you use
217 * PostgreSQL jdbc drivers V8.0 or newer, those methods are deprecated due
218 * to some class loader problems (but still work for now), and you may want
219 * to use the method below instead.
220 *
221 * @param pgconn The PGConnection object to add the types to
222 * @throws SQLException when a SQLException occurs
223 *
224 */
225 public static void addGISTypes(final PGConnection pgconn) throws SQLException {
226 loadTypesAdder("74").addGT((Connection) pgconn, false);
227 }
228
229
230 /**
231 * adds the JTS/PostGIS Data types to a PG 8.0+ Connection.
232 *
233 * @param pgconn The PGConnection object to add the types to
234 * @throws SQLException when a SQLException occurs
235 */
236 public static void addGISTypes80(final PGConnection pgconn) throws SQLException {
237 loadTypesAdder("80").addGT((Connection) pgconn, false);
238 }
239
240
241 /**
242 * adds the JTS/PostGIS Data types to a PG 7.2 Connection.
243 *
244 * @param pgconn The PGConnection object to add the types to
245 * @throws SQLException when a SQLException occurs
246 */
247 public static void addGISTypes72(final org.postgresql.PGConnection pgconn) throws SQLException {
248 loadTypesAdder("72").addGT((Connection) pgconn, false);
249 }
250
251
252 /**
253 * Mangles the PostGIS URL to return the original PostGreSQL URL
254 *
255 * @param url String containing the url to be "mangled"
256 * @return "mangled" string
257 * @throws SQLException when a SQLException occurs
258 */
259 protected String mangleURL(final String url) throws SQLException {
260 String myProgo = getProtoString();
261 if (url.startsWith(myProgo)) {
262 return POSTGRES_PROTOCOL + url.substring(myProgo.length());
263 } else {
264 throw new SQLException("Unknown protocol or subprotocol in url " + url);
265 }
266 }
267
268
269 protected String getProtoString() {
270 return POSTGIS_PROTOCOL;
271 }
272
273
274 /** Base class for the three typewrapper implementations */
275 protected abstract static class TypesAdder {
276 public final void addGT(final java.sql.Connection conn, final boolean lw) throws SQLException {
277 if (lw) {
278 addBinaryGeometries(conn);
279 } else {
280 addGeometries(conn);
281 }
282 addBoxen(conn);
283 }
284
285 public abstract void addGeometries(final Connection conn) throws SQLException;
286
287 public abstract void addBoxen(final Connection conn) throws SQLException;
288
289 public abstract void addBinaryGeometries(final Connection conn) throws SQLException;
290 }
291
292
293 /** addGISTypes for V7.3 and V7.4 pgjdbc */
294 protected static final class TypesAdder74 extends TypesAdder {
295
296 /** {@inheritDoc} */
297 @Override
298 public void addGeometries(final Connection conn) throws SQLException {
299 PGConnection pgconn = (PGConnection) conn;
300 pgconn.addDataType("geometry", org.postgis.PGgeometry.class);
301 pgconn.addDataType("public.geometry", org.postgis.PGgeometry.class);
302 pgconn.addDataType("\"public\".\"geometry\"", org.postgis.PGgeometry.class);
303
304 pgconn.addDataType("geography", org.postgis.PGgeography.class);
305 pgconn.addDataType("public.geography", org.postgis.PGgeography.class);
306 pgconn.addDataType("\"public\".\"geography\"", org.postgis.PGgeography.class);
307 }
308
309 /** {@inheritDoc} */
310 @Override
311 public void addBoxen(final Connection conn) throws SQLException {
312 PGConnection pgconn = (PGConnection) conn;
313 pgconn.addDataType("box3d", org.postgis.PGbox3d.class);
314 pgconn.addDataType("box2d", org.postgis.PGbox2d.class);
315 }
316
317 /** {@inheritDoc} */
318 @Override
319 public void addBinaryGeometries(final Connection conn) throws SQLException {
320 PGConnection pgconn = (PGConnection) conn;
321 pgconn.addDataType("geometry", org.postgis.PGgeometryLW.class);
322 pgconn.addDataType("geography", org.postgis.PGgeographyLW.class);
323 }
324 }
325
326
327 /** addGISTypes for V7.2 pgjdbc */
328 protected static class TypesAdder72 extends TypesAdder {
329
330 /** {@inheritDoc} */
331 @Override
332 public void addGeometries(final Connection conn) throws SQLException {
333 org.postgresql.PGConnection pgconn = (org.postgresql.PGConnection) conn;
334 pgconn.addDataType("geometry", org.postgis.PGgeometry.class);
335 pgconn.addDataType("public.geometry", org.postgis.PGgeometry.class);
336 pgconn.addDataType("\"public\".\"geometry\"", org.postgis.PGgeometry.class);
337
338 pgconn.addDataType("geography", org.postgis.PGgeography.class);
339 pgconn.addDataType("public.geography", org.postgis.PGgeography.class);
340 pgconn.addDataType("\"public\".\"geography\"", org.postgis.PGgeography.class);
341 }
342
343 /** {@inheritDoc} */
344 @Override
345 public void addBoxen(final Connection conn) throws SQLException {
346 org.postgresql.PGConnection pgconn = (org.postgresql.PGConnection) conn;
347 pgconn.addDataType("box3d", org.postgis.PGbox3d.class);
348 pgconn.addDataType("box2d", org.postgis.PGbox2d.class);
349 }
350
351 /** {@inheritDoc} */
352 @Override
353 public void addBinaryGeometries(final Connection conn) throws SQLException {
354 org.postgresql.PGConnection pgconn = (org.postgresql.PGConnection) conn;
355 pgconn.addDataType("geometry", org.postgis.PGgeometryLW.class);
356 pgconn.addDataType("geography", org.postgis.PGgeographyLW.class);
357 }
358 }
359
360
361 /** addGISTypes for V8.0 (and hopefully newer) pgjdbc */
362 protected static class TypesAdder80 extends TypesAdder {
363
364 /** {@inheritDoc} */
365 @Override
366 public void addGeometries(final Connection conn) throws SQLException {
367 PGConnection pgconn = (PGConnection) conn;
368 pgconn.addDataType("geometry", org.postgis.PGgeometry.class);
369 pgconn.addDataType("public.geometry", org.postgis.PGgeometry.class);
370 pgconn.addDataType("\"public\".\"geometry\"", org.postgis.PGgeometry.class);
371
372 pgconn.addDataType("geography", org.postgis.PGgeometry.class);
373 pgconn.addDataType("public.geography", org.postgis.PGgeometry.class);
374 pgconn.addDataType("\"public\".\"geography\"", org.postgis.PGgeometry.class);
375 }
376
377 /** {@inheritDoc} */
378 @Override
379 public void addBoxen(final Connection conn) throws SQLException {
380 PGConnection pgconn = (PGConnection) conn;
381 pgconn.addDataType("box3d", org.postgis.PGbox3d.class);
382 pgconn.addDataType("box2d", org.postgis.PGbox2d.class);
383 }
384
385 /** {@inheritDoc} */
386 @Override
387 public void addBinaryGeometries(final Connection conn) throws SQLException {
388 PGConnection pgconn = (PGConnection) conn;
389 pgconn.addDataType("geometry", org.postgis.PGgeometryLW.class);
390 pgconn.addDataType("geography", org.postgis.PGgeographyLW.class);
391 }
392 }
393
394
395 /** {@inheritDoc} */
396 @Override
397 public Logger getParentLogger() {
398 throw new UnsupportedOperationException("Not supported yet.");
399 }
400
401
402 }
+0
-115
jdbc/src/main/java/org/postgis/DriverWrapperAutoprobe.java less more
0 /*
1 * DriverWrapperAutoprobe.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - Wrapper utility class
4 *
5 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
6 *
7 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24
25 package org.postgis;
26
27 import org.postgresql.Driver;
28
29 import java.sql.Connection;
30 import java.sql.ResultSet;
31 import java.sql.SQLException;
32 import java.sql.Statement;
33 import java.util.logging.Level;
34
35 /**
36 * DriverWrapperAutoprobe
37 *
38 * Wraps the PostGreSQL Driver to transparently add the PostGIS Object Classes.
39 * This avoids the need of explicit addDataType() calls from the driver users
40 * side.
41 *
42 * This DriverWrapper tries to autoprobe the installed PostGIS version to decide
43 * whether to use EWKT or hex encoded EWKB as canonical text representation. It
44 * uses the first PostGIS installation found in your namespace search path (aka
45 * schema search path) on the server side, and this works as long as you do not
46 * access incompatible PostGIS versions that reside in other schemas.
47 *
48 * For usage notes, see DriverWrapper class, but use "jdbc:postgresql_autogis:"
49 * as JDBC url prefix and org.postgis.DriverWrapperAutoprobe as driver class.
50 *
51 * @author {@literal Markus Schaber <markus.schaber@logix-tt.com>}
52 * @see DriverWrapper
53 */
54 public class DriverWrapperAutoprobe extends DriverWrapper {
55
56 public static final String POSTGIS_AUTOPROTOCOL = "jdbc:postgresql_autogis:";
57 public static final String REVISIONAUTO = "$Revision$";
58
59 /**
60 * Default constructor.
61 *
62 * @throws SQLException when a SQLExceptin occurs
63 */
64 public DriverWrapperAutoprobe() throws SQLException {
65 super();
66 }
67
68 static {
69 try {
70 // Try to register ourself to the DriverManager
71 java.sql.DriverManager.registerDriver(new DriverWrapperAutoprobe());
72 } catch (SQLException e) {
73 logger.log(Level.WARNING, "Error registering PostGIS LW Wrapper Driver", e);
74 }
75 }
76
77 protected String getProtoString() {
78 return POSTGIS_AUTOPROTOCOL;
79 }
80
81 protected boolean useLW(Connection conn) {
82 try {
83 return supportsEWKB(conn);
84 } catch (SQLException e) {
85 // fail safe default
86 return false;
87 }
88 }
89
90 /**
91 * Returns our own CVS version plus postgres Version
92 *
93 * @return String value reprenstation of the version
94 */
95 public static String getVersion() {
96 return "PostGisWrapperAutoprobe " + REVISIONAUTO + ", wrapping " + Driver.getVersion();
97 }
98
99 public static boolean supportsEWKB(Connection conn) throws SQLException {
100 Statement stat = conn.createStatement();
101 ResultSet rs = stat.executeQuery("SELECT postgis_version()");
102 rs.next();
103 String version = rs.getString(1);
104 rs.close();
105 stat.close();
106 if (version == null) {
107 throw new SQLException("postgis_version returned NULL!");
108 }
109 version = version.trim();
110 int idx = version.indexOf('.');
111 int majorVersion = Integer.parseInt(version.substring(0, idx));
112 return majorVersion >= 1;
113 }
114 }
+0
-89
jdbc/src/main/java/org/postgis/DriverWrapperLW.java less more
0 /*
1 * DriverWrapperLW.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - Wrapper utility class
4 *
5 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
6 *
7 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24
25 package org.postgis;
26
27 import org.postgresql.Driver;
28
29 import java.sql.Connection;
30 import java.sql.SQLException;
31 import java.util.logging.Level;
32
33 /**
34 * DriverWrapperLW
35 *
36 * Wraps the PostGreSQL Driver to transparently add the PostGIS Object Classes.
37 * This avoids the need of explicit addDataType() calls from the driver users
38 * side.
39 *
40 * This DriverWrapper subclass always uses hex encoded EWKB as canonical text
41 * representation, and thus only works against PostGIS 1.x servers and newer.
42 *
43 * For usage notes, see DriverWrapper class, but use "jdbc:postgresql_lwgis:" as
44 * JDBC url prefix and org.postgis.DriverWrapperLW as driver class.
45 *
46 * @author {@literal Markus Schaber <markus.schaber@logix-tt.com>}
47 * @see DriverWrapper
48 */
49 public class DriverWrapperLW extends DriverWrapper {
50
51 public static final String POSTGIS_LWPROTOCOL = "jdbc:postgresql_lwgis:";
52 public static final String REVISIONLW = "$Revision$";
53
54 /**
55 * Default constructor.
56 *
57 * @throws SQLException when a SQLException occurs
58 */
59 public DriverWrapperLW() throws SQLException {
60 super();
61 }
62
63 static {
64 try {
65 // Try to register ourself to the DriverManager
66 java.sql.DriverManager.registerDriver(new DriverWrapperLW());
67 } catch (SQLException e) {
68 logger.log(Level.WARNING, "Error registering PostGIS LW Wrapper Driver", e);
69 }
70 }
71
72 protected String getProtoString() {
73 return POSTGIS_LWPROTOCOL;
74 }
75
76 protected boolean useLW(Connection result) {
77 return true;
78 }
79
80 /**
81 * Returns our own CVS version plus postgres Version
82 *
83 * @return String value reprenstation of the version
84 */
85 public static String getVersion() {
86 return "PostGisWrapperLW " + REVISIONLW + ", wrapping " + Driver.getVersion();
87 }
88 }
+0
-67
jdbc/src/main/java/org/postgis/PGbox2d.java less more
0 /*
1 * PGbox2d.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - bounding box model
4 *
5 * (C) 2004 Paul Ramsey, pramsey@refractions.net
6 *
7 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
8 *
9 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 */
26
27 package org.postgis;
28
29 import java.sql.SQLException;
30
31 public class PGbox2d extends PGboxbase {
32 /* JDK 1.5 Serialization */
33 private static final long serialVersionUID = 0x100;
34
35 public PGbox2d() {
36 super();
37 }
38
39 public PGbox2d(Point llb, Point urt) {
40 super(llb, urt);
41 }
42
43 public PGbox2d(String value) throws SQLException {
44 super(value);
45 }
46
47 public void setValue(String value) throws SQLException {
48 super.setValue(value);
49
50 if (llb.dimension != 2 || urt.dimension != 2) {
51 throw new SQLException("PGbox2d is only allowed to have 2 dimensions!");
52 }
53 }
54
55 public String getPrefix() {
56 return "BOX";
57 }
58
59 public String getPGtype() {
60 return "box2d";
61 }
62
63 protected PGboxbase newInstance() {
64 return new PGbox2d();
65 }
66 }
+0
-60
jdbc/src/main/java/org/postgis/PGbox3d.java less more
0 /*
1 * PGbox3d.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - bounding box model
4 *
5 *
6 * (C) 2004 Paul Ramsey, pramsey@refractions.net
7 *
8 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
9 *
10 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
11 *
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
16 *
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
21 *
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 *
26 */
27
28 package org.postgis;
29
30 import java.sql.SQLException;
31
32 public class PGbox3d extends PGboxbase {
33 /* JDK 1.5 Serialization */
34 private static final long serialVersionUID = 0x100;
35
36 public PGbox3d() {
37 super();
38 }
39
40 public PGbox3d(Point llb, Point urt) {
41 super(llb, urt);
42 }
43
44 public PGbox3d(String value) throws SQLException {
45 super(value);
46 }
47
48 public String getPrefix() {
49 return ("BOX3D");
50 }
51
52 public String getPGtype() {
53 return ("box3d");
54 }
55
56 protected PGboxbase newInstance() {
57 return new PGbox3d();
58 }
59 }
+0
-197
jdbc/src/main/java/org/postgis/PGboxbase.java less more
0 /*
1 * PGboxbase.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - bounding box model
4 *
5 *
6 * (C) 2004 Paul Ramsey, pramsey@refractions.net
7 *
8 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
9 *
10 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
11 *
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
16 *
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
21 *
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 *
26 */
27
28 package org.postgis;
29
30 import org.postgresql.util.PGobject;
31
32 import java.sql.SQLException;
33 import java.util.List;
34
35 /*
36 * Updates Oct 2002 - data members made private - getLLB() and getURT() methods
37 * added
38 */
39
40 public abstract class PGboxbase extends PGobject {
41 /* JDK 1.5 Serialization */
42 private static final long serialVersionUID = 0x100;
43
44 /**
45 * The lower left bottom corner of the box.
46 */
47 protected Point llb;
48
49 /**
50 * The upper right top corner of the box.
51 */
52 protected Point urt;
53
54 /**
55 * The Prefix we have in WKT rep.
56 *
57 * I use an abstract method here so we do not need to replicate the String
58 * object in every instance.
59 *
60 * @return the prefix, as a string
61 */
62 public abstract String getPrefix();
63
64 /**
65 * The Postgres type we have (same construct as getPrefix())
66 *
67 * @return String containing the name of the type for this box.
68 */
69 public abstract String getPGtype();
70
71 public PGboxbase() {
72 this.setType(getPGtype());
73 }
74
75 public PGboxbase(Point llb, Point urt) {
76 this();
77 this.llb = llb;
78 this.urt = urt;
79 }
80
81 public PGboxbase(String value) throws SQLException {
82 this();
83 setValue(value);
84 }
85
86 public void setValue(String value) throws SQLException {
87 int srid = Geometry.UNKNOWN_SRID;
88 value = value.trim();
89 if (value.startsWith("SRID=")) {
90 String[] temp = GeometryBuilder.splitSRID(value);
91 value = temp[1].trim();
92 srid = Geometry.parseSRID(Integer.parseInt(temp[0].substring(5)));
93 }
94 String myPrefix = getPrefix();
95 if (value.startsWith(myPrefix)) {
96 value = value.substring(myPrefix.length()).trim();
97 }
98 String valueNoParans = GeometryTokenizer.removeLeadingAndTrailingStrings(value.trim(), "(", ")");
99 List<String> tokens = GeometryTokenizer.tokenize(valueNoParans, ',');
100 llb = new Point(tokens.get(0));
101 urt = new Point(tokens.get(1));
102 if (srid != Geometry.UNKNOWN_SRID) {
103 llb.setSrid(srid);
104 urt.setSrid(srid);
105 }
106 }
107
108 public String getValue() {
109 StringBuffer sb = new StringBuffer();
110 outerWKT(sb);
111 return sb.toString();
112 }
113
114 private void outerWKT(StringBuffer sb) {
115 sb.append(getPrefix());
116 sb.append('(');
117 llb.innerWKT(sb);
118 sb.append(',');
119 urt.innerWKT(sb);
120 sb.append(')');
121 }
122
123 /**
124 * Unlike geometries, toString() does _not_ contain the srid, as server-side
125 * PostGIS cannot parse this.
126 *
127 * @return String representation of this box
128 */
129 public String toString() {
130 return getValue();
131 }
132
133 /**
134 * Returns the lower left bottom corner of the box as a Point object
135 *
136 * @return lower left bottom corner of this box
137 */
138 public Point getLLB() {
139 return llb;
140 }
141
142 /**
143 * Returns the upper right top corner of the box as a Point object
144 *
145 * @return upper right top corner of this box
146 */
147 public Point getURT() {
148 return urt;
149 }
150
151 public boolean equals(Object other) {
152 if (other instanceof PGboxbase) {
153 PGboxbase otherbox = (PGboxbase) other;
154 return (compareLazyDim(this.llb, otherbox.llb) && compareLazyDim(this.urt, otherbox.urt));
155 }
156 return false;
157 }
158
159 /**
160 * Compare two coordinates with lazy dimension checking.
161 *
162 * As the Server always returns Box3D with three dimensions, z==0 equals
163 * dimensions==2
164 *
165 * @param first First of two points to be compared
166 * @param second Second of two points to be compared
167 * @return true if the points are the same, false otherwise
168 *
169 */
170 protected static boolean compareLazyDim(Point first, Point second) {
171 return first.x == second.x
172 && first.y == second.y
173 && (((first.dimension == 2 || first.z == 0.0) && (second.dimension == 2 || second.z == 0)) || (first.z == second.z));
174 }
175
176 public Object clone() {
177 PGboxbase obj = newInstance();
178 obj.llb = this.llb;
179 obj.urt = this.urt;
180 obj.setType(type);
181 return obj;
182 }
183
184 /**
185 * Obtain a new instance of a PGboxbase
186 *
187 * We could have used this.getClass().newInstance() here, but this forces us
188 * dealing with InstantiationException and IllegalAccessException. Due to
189 * the PGObject.clone() brokennes that does not allow clone() to throw
190 * CloneNotSupportedException, we cannot even pass this exceptions down to
191 * callers in a sane way.
192 *
193 * @return a new instance of PGboxbase
194 */
195 protected abstract PGboxbase newInstance();
196 }
+0
-133
jdbc/src/main/java/org/postgis/PGgeo.java less more
0 /*
1 * This library is free software; you can redistribute it and/or
2 * modify it under the terms of the GNU Lesser General Public
3 * License as published by the Free Software Foundation; either
4 * version 2.1 of the License, or (at your option) any later version.
5 *
6 * This library is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 * Lesser General Public License for more details.
10 *
11 * You should have received a copy of the GNU Lesser General Public
12 * License along with this library; if not, write to the Free Software
13 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
14 *
15 * (C) 2004 Paul Ramsey, pramsey@refractions.net
16 *
17 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
18 *
19 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
20 */
21
22 package org.postgis;
23
24
25 import org.postgis.binary.BinaryParser;
26 import org.postgresql.util.PGobject;
27
28 import java.sql.SQLException;
29
30
31 /**
32 * A PostgreSQL JDBC PGobject extension data type modeling a "geo" type.
33 *
34 * This class serves as a common superclass for classes such as PGgeometry and PGgeography which model
35 * more specific type semantics.
36 *
37 * @author Phillip Ross
38 */
39 public class PGgeo extends PGobject {
40
41 private static final long serialVersionUID = -3181366908975582090L;
42
43 /** The encapsulated geometry. */
44 Geometry geometry;
45
46
47 /** Instantiate with default state. */
48 protected PGgeo() {
49 }
50
51
52 /**
53 * Instantiate with the specified state.
54 *
55 * @param geometry the geometry to instantiate with
56 */
57 public PGgeo(final Geometry geometry) {
58 this();
59 this.geometry = geometry;
60 }
61
62
63 /**
64 * Instantiate with the specified state.
65 *
66 * @param value the value to instantiate with
67 */
68 public PGgeo(final String value) throws SQLException {
69 this();
70 setValue(value);
71 }
72
73
74 /** {@inheritDoc} */
75 @Override
76 public String getValue() {
77 return geometry.toString();
78 }
79
80
81 /** {@inheritDoc} */
82 @Override
83 public void setValue(final String value) throws SQLException {
84 geometry = GeometryBuilder.geomFromString(value, new BinaryParser());
85 }
86
87
88 /**
89 * Get the encapsulated geometry.
90 *
91 * @return the encapsulated geomtery
92 */
93 public Geometry getGeometry() {
94 return geometry;
95 }
96
97
98 /**
99 * Set the encapsulated geometry.
100 *
101 * @param geometry the encapsulated geometry
102 */
103 public void setGeometry(final Geometry geometry) {
104 this.geometry = geometry;
105 }
106
107
108 /**
109 * Get the type of the encapsulated geometry.
110 *
111 * @return the type of the encapsulated geometry
112 */
113 public int getGeoType() {
114 return geometry.type;
115 }
116
117
118 /** {@inheritDoc} */
119 @Override
120 public String toString() {
121 return geometry.toString();
122 }
123
124
125 /** {@inheritDoc} */
126 @Override
127 public Object clone() {
128 return new PGgeo(geometry);
129 }
130
131
132 }
+0
-77
jdbc/src/main/java/org/postgis/PGgeography.java less more
0 /*
1 * This library is free software; you can redistribute it and/or
2 * modify it under the terms of the GNU Lesser General Public
3 * License as published by the Free Software Foundation; either
4 * version 2.1 of the License, or (at your option) any later version.
5 *
6 * This library is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 * Lesser General Public License for more details.
10 *
11 * You should have received a copy of the GNU Lesser General Public
12 * License along with this library; if not, write to the Free Software
13 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
14 *
15 * (C) 2004 Paul Ramsey, pramsey@refractions.net
16 *
17 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
18 *
19 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
20 */
21
22 package org.postgis;
23
24
25 import java.sql.SQLException;
26
27
28 /**
29 * A PostgreSQL JDBC PGobject extension data type modeling the geography type.
30 *
31 * @author Phillip Ross
32 */
33 public class PGgeography extends PGgeo {
34
35 private static final long serialVersionUID = 3796853960196603896L;
36
37
38 /** Instantiate with default state. */
39 public PGgeography() {
40 super();
41 setType("geography");
42 }
43
44
45 /**
46 * Instantiate with the specified state.
47 *
48 * @param geometry the geometry to instantiate with
49 */
50 public PGgeography(final Geometry geometry) {
51 this();
52 this.geometry = geometry;
53 setType("geography");
54 }
55
56
57 /**
58 * Instantiate with the specified state.
59 *
60 * @param value the value to instantiate with
61 */
62 public PGgeography(final String value) throws SQLException {
63 this();
64 setValue(value);
65 setType("geography");
66 }
67
68
69 /** {@inheritDoc} */
70 @Override
71 public Object clone() {
72 return new PGgeography(geometry);
73 }
74
75
76 }
+0
-84
jdbc/src/main/java/org/postgis/PGgeographyLW.java less more
0 /*
1 * This library is free software; you can redistribute it and/or
2 * modify it under the terms of the GNU Lesser General Public
3 * License as published by the Free Software Foundation; either
4 * version 2.1 of the License, or (at your option) any later version.
5 *
6 * This library is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 * Lesser General Public License for more details.
10 *
11 * You should have received a copy of the GNU Lesser General Public
12 * License along with this library; if not, write to the Free Software
13 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
14 *
15 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
16 *
17 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
18 */
19
20 package org.postgis;
21
22
23 import org.postgis.binary.BinaryWriter;
24
25 import java.sql.SQLException;
26
27
28 /**
29 * A PostgreSQL JDBC PGobject extension data type modeling the geography type.
30 *
31 * The hex-encoded EWKB format is used to communicate with the backend, which is much more efficient,
32 * but only works with Lwgeom enabled PostGIS (1.0.0 and up).
33 *
34 * @author Phillip Ross
35 */
36 public class PGgeographyLW extends PGgeography {
37
38 private static final long serialVersionUID = 7717856818804158022L;
39
40 /** The binary writer to be used for serializing geometry to a PGobject value. */
41 BinaryWriter bw = new BinaryWriter();
42
43
44 /** Instantiate with default state. */
45 public PGgeographyLW() {
46 super();
47 }
48
49 /**
50 * Instantiate with the specified state.
51 *
52 * @param geometry the geometry to instantiate with
53 */
54 public PGgeographyLW(final Geometry geometry) {
55 super(geometry);
56 }
57
58
59 /**
60 * Instantiate with the specified state.
61 *
62 * @param value the value to instantiate with
63 */
64 public PGgeographyLW(final String value) throws SQLException {
65 super(value);
66 }
67
68
69 /** {@inheritDoc} */
70 @Override
71 public String getValue() {
72 return bw.writeHexed(geometry);
73 }
74
75
76 /** {@inheritDoc} */
77 @Override
78 public Object clone() {
79 return new PGgeographyLW(geometry);
80 }
81
82
83 }
+0
-75
jdbc/src/main/java/org/postgis/PGgeometry.java less more
0 /*
1 * This library is free software; you can redistribute it and/or
2 * modify it under the terms of the GNU Lesser General Public
3 * License as published by the Free Software Foundation; either
4 * version 2.1 of the License, or (at your option) any later version.
5 *
6 * This library is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 * Lesser General Public License for more details.
10 *
11 * You should have received a copy of the GNU Lesser General Public
12 * License along with this library; if not, write to the Free Software
13 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
14 *
15 * (C) 2004 Paul Ramsey, pramsey@refractions.net
16 *
17 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
18 *
19 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
20 */
21
22 package org.postgis;
23
24
25 import java.sql.SQLException;
26
27
28 /**
29 * A PostgreSQL JDBC PGobject extension data type modeling the geometry type.
30 *
31 * @author Phillip Ross
32 */
33 public class PGgeometry extends PGgeo {
34
35 private static final long serialVersionUID = 4116907189503026815L;
36
37
38 /** Instantiate with default state. */
39 public PGgeometry() {
40 super();
41 setType("geometry");
42 }
43
44
45 /**
46 * Instantiate with the specified state.
47 *
48 * @param geometry the geometry to instantiate with
49 */
50 public PGgeometry(final Geometry geometry) {
51 super(geometry);
52 setType("geometry");
53 }
54
55
56 /**
57 * Instantiate with the specified state.
58 *
59 * @param value the value to instantiate with
60 */
61 public PGgeometry(final String value) throws SQLException {
62 super(value);
63 setType("geometry");
64 }
65
66
67 /** {@inheritDoc} */
68 @Override
69 public Object clone() {
70 return new PGgeometry(geometry);
71 }
72
73
74 }
+0
-85
jdbc/src/main/java/org/postgis/PGgeometryLW.java less more
0 /*
1 * This library is free software; you can redistribute it and/or
2 * modify it under the terms of the GNU Lesser General Public
3 * License as published by the Free Software Foundation; either
4 * version 2.1 of the License, or (at your option) any later version.
5 *
6 * This library is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 * Lesser General Public License for more details.
10 *
11 * You should have received a copy of the GNU Lesser General Public
12 * License along with this library; if not, write to the Free Software
13 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
14 *
15 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
16 *
17 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
18 */
19
20 package org.postgis;
21
22
23 import org.postgis.binary.BinaryWriter;
24
25 import java.sql.SQLException;
26
27
28 /**
29 * A PostgreSQL JDBC PGobject extension data type modeling the geometry type.
30 *
31 * The hex-encoded EWKB format is used to communicate with the backend, which is much more efficient,
32 * but only works with Lwgeom enabled PostGIS (1.0.0 and up).
33 *
34 * @author Phillip Ross
35 */
36 public class PGgeometryLW extends PGgeometry {
37
38 private static final long serialVersionUID = -7774502289413094862L;
39
40 /** The binary writer to be used for serializing geometry to a PGobject value. */
41 BinaryWriter bw = new BinaryWriter();
42
43
44 /** Instantiate with default state. */
45 public PGgeometryLW() {
46 super();
47 }
48
49
50 /**
51 * Instantiate with the specified state.
52 *
53 * @param geometry the geometry to instantiate with
54 */
55 public PGgeometryLW(final Geometry geometry) {
56 super(geometry);
57 }
58
59
60 /**
61 * Instantiate with the specified state.
62 *
63 * @param value the value to instantiate with
64 */
65 public PGgeometryLW(final String value) throws SQLException {
66 super(value);
67 }
68
69
70 /** {@inheritDoc} */
71 @Override
72 public String getValue() {
73 return bw.writeHexed(geometry);
74 }
75
76
77 /** {@inheritDoc} */
78 @Override
79 public Object clone() {
80 return new PGgeometryLW(geometry);
81 }
82
83
84 }
+0
-119
jdbc/src/main/java/org/postgis/Version.java less more
0 /*
1 * Version.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - current version identification
4 *
5 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
6 *
7 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24
25 package org.postgis;
26
27
28 import java.io.IOException;
29 import java.util.Properties;
30
31
32 /** Corresponds to the appropriate PostGIS that carried this source */
33 public class Version {
34
35 /** We read our version information from this resource... */
36 private static final String RESOURCE_FILENAME = "org/postgis/version.properties";
37
38 private static final String VERSION_PROPERTY_NAME = "VERSION";
39
40 public static final String VERSION;
41
42 /** The major version */
43 public static final int MAJOR;
44
45 /** The minor version */
46 public static final int MINOR;
47
48 /**
49 * The micro version, usually a number including possibly textual suffixes
50 * like RC3.
51 */
52 public static final String MICRO;
53
54 static {
55 int major = -1;
56 int minor = -1;
57 String micro = null;
58 String version = null;
59 try {
60 ClassLoader loader = Version.class.getClassLoader();
61
62 Properties prop = new Properties();
63 try {
64 prop.load(loader.getResourceAsStream(RESOURCE_FILENAME));
65 } catch (IOException e) {
66 throw new ExceptionInInitializerError("Error initializing PostGIS JDBC version. Cause: Ressource "
67 + RESOURCE_FILENAME + " cannot be read. " + e.getMessage());
68 } catch (NullPointerException e) {
69 throw new ExceptionInInitializerError("Error initializing PostGIS JDBC version. Cause: Ressource "
70 + RESOURCE_FILENAME + " not found. " + e.getMessage());
71 }
72
73 version = prop.getProperty(VERSION_PROPERTY_NAME);
74 if (version == null) {
75 throw new ExceptionInInitializerError("Error initializing PostGIS JDBC version: Missing " + VERSION_PROPERTY_NAME + " property.");
76 } else if (version.equals("")) {
77 throw new ExceptionInInitializerError("Error initializing PostGIS JDBC version: Empty " + VERSION_PROPERTY_NAME + " property.");
78 } else {
79 String[] versions = version.split("\\.");
80 if (version.length() < 3) {
81 throw new ExceptionInInitializerError("Error initializing PostGIS JDBC version: FULL_VERSION (" + version + ") does not contain 3 components ");
82 }
83 if (versions.length >= 1) {
84 try {
85 major = Integer.parseInt(versions[0]);
86 } catch (NumberFormatException nfe) {
87 throw new ExceptionInInitializerError("Error initializing PostGIS JDBC version! Error parsing major version ");
88 }
89 }
90 if (versions.length >= 2) {
91 try {
92 minor = Integer.parseInt(versions[1]);
93 } catch (NumberFormatException nfe) {
94 throw new ExceptionInInitializerError("Error initializing PostGIS JDBC version! Error parsing minor version ");
95 }
96 }
97 if (version.length() >= 3) {
98 micro = versions[2];
99 }
100 }
101
102 } finally {
103 MAJOR = major;
104 MINOR = minor;
105 MICRO = micro;
106 VERSION = version;
107 }
108 }
109
110 /** Full version for human reading - code should use the constants above */
111 public static final String FULL = "PostGIS JDBC V" + MAJOR + "." + MINOR + "." + MICRO;
112
113 public static String getFullVersion() {
114 return FULL;
115 }
116
117
118 }
+0
-5
jdbc/src/main/javadoc/overview.html less more
0 <body>
1 <p>The JDBC extensions provide Java objects corresponding to the internal PostGIS types. These objects can be used
2 to write Java clients which query the PostGIS database and draw or do calculations on the GIS data in PostGIS.
3 </p>
4 </body>
+0
-1
jdbc/src/main/resources/org/postgis/version.properties less more
0 VERSION=${version}
+0
-9
jdbc/src/main/resources/org/postgresql/driverconfig.properties less more
0 #
1 # This property file is included in the postgis jar and autoregisters the
2 # PostGIS datatypes within the jdbc driver.
3 #
4
5 datatype.geometry=org.postgis.PGgeometry
6 datatype.geography=org.postgis.PGgeography
7 datatype.box3d=org.postgis.PGbox3d
8 datatype.box2d=org.postgis.PGbox2d
+0
-135
jdbc/src/test/java/org/postgis/BoxesTest.java less more
0 /*
1 * BoxesTest.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - example and test classes
4 *
5 * (C) 2004 Paul Ramsey, pramsey@refractions.net
6 *
7 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
8 *
9 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 */
26
27 package org.postgis;
28
29
30 import net.postgis.tools.testutils.TestContainerController;
31 import org.postgis.util.VersionUtil;
32 import org.postgresql.util.PGobject;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35 import org.testng.Assert;
36 import org.testng.ITestContext;
37 import org.testng.annotations.AfterClass;
38 import org.testng.annotations.BeforeClass;
39 import org.testng.annotations.Test;
40
41 import java.sql.*;
42
43
44 public class BoxesTest {
45
46 private static final Logger logger = LoggerFactory.getLogger(BoxesTest.class);
47
48 /** Our test candidates: */
49 public static final String[] BOXEN3D = new String[]{
50 "BOX3D(1 2 3,4 5 6)", // 3d variant
51 "BOX3D(1 2,4 5)"// 2d variant
52 };
53
54 public static final String[] BOXEN2D = new String[]{"BOX(1 2,3 4)"};
55
56 private Connection connection = null;
57
58
59 @Test
60 public void testBoxes() throws Exception {
61 for (String aBOXEN3D : BOXEN3D) {
62 PGbox3d candidate = new PGbox3d(aBOXEN3D);
63 test(aBOXEN3D, candidate, false);
64 }
65 for (String aBOXEN2D : BOXEN2D) {
66 PGbox2d candidate = new PGbox2d(aBOXEN2D);
67 test(aBOXEN2D, candidate, true);
68 }
69 }
70
71
72 public void test(String orig, PGobject candidate, boolean newPostgisOnly) throws Exception {
73 logger.debug("Original: {}", orig);
74 String redone = candidate.toString();
75 logger.debug("Parsed: {}", redone);
76 Assert.assertEquals(orig, redone, "Recreated Text Rep not equal");
77
78 // Simulate the way postgresql-jdbc uses to create PGobjects
79 PGobject recreated = candidate.getClass().newInstance();
80 recreated.setValue(redone);
81
82 String reparsed = recreated.toString();
83 logger.debug("Re-Parsed: " + reparsed);
84 Assert.assertEquals(recreated, candidate, "Recreated boxen are not equal");
85 Assert.assertEquals(reparsed, orig, "2nd generation text reps are not equal");
86
87 logger.debug("testing on connection: {}", connection.getCatalog());
88 Statement statement = connection.createStatement();
89 if (newPostgisOnly && Integer.parseInt(VersionUtil.retrievePostGISServerMajorVersion(connection)) < 1) {
90 logger.debug("PostGIS version is too old, not testing box2d");
91 } else {
92 PGobject sqlGeom = viaSQL(candidate, statement);
93 logger.debug("SQLin : " + sqlGeom.toString());
94 Assert.assertEquals(candidate, sqlGeom, "Geometries after SQL are not equal");
95 PGobject sqlreGeom = viaSQL(recreated, statement);
96 logger.debug("SQLout : " + sqlreGeom.toString());
97 Assert.assertEquals(candidate, sqlreGeom, "reparsed Geometries after SQL are not equal");
98 }
99 statement.close();
100 }
101
102
103 /** Pass a geometry representation through the SQL server */
104 private static PGobject viaSQL(PGobject obj, Statement stat) throws SQLException {
105 ResultSet rs = stat.executeQuery("SELECT '" + obj.toString() + "'::" + obj.getType());
106 rs.next();
107 return (PGobject) rs.getObject(1);
108 }
109
110
111 @BeforeClass
112 public void initJdbcConnection(ITestContext ctx) throws Exception {
113 final String jdbcUrlSuffix = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_JDBC_URL_SUFFIX);
114 Assert.assertNotNull(jdbcUrlSuffix);
115 final String jdbcUrl = "jdbc:postgresql" + jdbcUrlSuffix;
116 final String jdbcUsername = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_USER_PARAM_NAME);
117 Assert.assertNotNull(jdbcUsername);
118 final String jdbcPassword = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_PW_PARAM_NAME);
119 Assert.assertNotNull(jdbcPassword);
120 Class.forName("org.postgis.DriverWrapper");
121 connection = DriverManager.getConnection(jdbcUrl, jdbcUsername, jdbcPassword);
122 }
123
124
125 @AfterClass
126 public void shutdown() throws Exception {
127 logger.debug("shutting down");
128 if (connection != null) {
129 connection.close();
130 }
131 }
132
133
134 }
+0
-144
jdbc/src/test/java/org/postgis/DatatypesAutoRegistrationTest.java less more
0 /*
1 * This library is free software; you can redistribute it and/or
2 * modify it under the terms of the GNU Lesser General Public
3 * License as published by the Free Software Foundation; either
4 * version 2.1 of the License, or (at your option) any later version.
5 *
6 * This library is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 * Lesser General Public License for more details.
10 *
11 * You should have received a copy of the GNU Lesser General Public
12 * License along with this library; if not, write to the Free Software
13 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
14 *
15 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
16 *
17 * (C) 2020 Phillip Ross, phillip.w.g.ross@gmail.com
18 */
19
20 package org.postgis;
21
22
23 import net.postgis.tools.testutils.TestContainerController;
24 import org.postgis.util.VersionUtil;
25 import org.postgresql.Driver;
26 import org.postgresql.util.PGobject;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
29 import org.testng.Assert;
30 import org.testng.ITestContext;
31 import org.testng.annotations.AfterMethod;
32 import org.testng.annotations.BeforeMethod;
33 import org.testng.annotations.Test;
34
35 import java.sql.Connection;
36 import java.sql.DriverManager;
37 import java.sql.ResultSet;
38 import java.sql.Statement;
39
40
41 /**
42 * This test program tests whether the auto-registration of PostGIS data types within the postgresql jdbc driver was
43 * successful. It also checks for PostGIS version to know whether box2d is available.
44 */
45 public class DatatypesAutoRegistrationTest {
46
47 /** The static logger instance. */
48 private static final Logger logger = LoggerFactory.getLogger(DatatypesAutoRegistrationTest.class);
49
50 /** The JDBC Connection to be used for tests. */
51 private Connection connection;
52
53
54 /**
55 * Initializes a new JDBC Connection.
56 *
57 * @param ctx the test context
58 * @throws Exception when an exception occurs
59 */
60 @BeforeMethod
61 public void initJdbcConnection(ITestContext ctx) throws Exception {
62 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
63 final String jdbcUrlSuffix = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_JDBC_URL_SUFFIX);
64 Assert.assertNotNull(jdbcUrlSuffix);
65 final String jdbcUrl = "jdbc:postgresql" + jdbcUrlSuffix;
66 final String jdbcUsername = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_USER_PARAM_NAME);
67 Assert.assertNotNull(jdbcUsername);
68 final String jdbcPassword = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_PW_PARAM_NAME);
69 Assert.assertNotNull(jdbcPassword);
70 connection = DriverManager.getConnection(jdbcUrl, jdbcUsername, jdbcPassword);
71 }
72
73
74 /**
75 * Un-allocates the JDBC connection.
76 *
77 * @throws Exception when an exception occurs
78 */
79 @AfterMethod
80 public void shutdown() throws Exception {
81 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
82 logger.debug("shutting down");
83 if (connection != null) {
84 connection.close();
85 }
86 }
87
88
89 @Test
90 public void testAutoRegistration() throws Exception {
91 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
92 Driver driver = new Driver();
93 int driverMajorVersion = driver.getMajorVersion();
94 int driverMinorVersion = driver.getMinorVersion();
95 logger.debug("Driver version: {}.{}", driverMajorVersion, driverMinorVersion);
96 if (driverMajorVersion < 8) {
97 logger.info(
98 "postgresql driver {}.{} is too old, it does not support auto-registration",
99 driverMajorVersion, driverMinorVersion
100 );
101 } else {
102 int postgisServerMajor = Integer.parseInt(VersionUtil.retrievePostGISServerMajorVersion(connection));
103 logger.debug("PostGIS Version: " + postgisServerMajor);
104 Assert.assertNotEquals(
105 postgisServerMajor,
106 0,
107 "Could not get PostGIS version. Is PostGIS really installed in the database?"
108 );
109 Statement statement = connection.createStatement();
110
111 // Test geometries
112 ResultSet resultSet = statement.executeQuery("SELECT 'POINT(1 2)'::geometry");
113 resultSet.next();
114 PGobject result = (PGobject) resultSet.getObject(1);
115 Assert.assertTrue(result instanceof PGgeometry);
116
117 // Test geography
118 resultSet = statement.executeQuery("SELECT 'POINT(1 2)'::geography");
119 resultSet.next();
120 Object geographyRawObject = resultSet.getObject(1);
121 result = (PGobject) resultSet.getObject(1);
122 Assert.assertTrue(result instanceof PGgeography);
123
124 // Test box3d
125 resultSet = statement.executeQuery("SELECT 'BOX3D(1 2 3, 4 5 6)'::box3d");
126 resultSet.next();
127 result = (PGobject) resultSet.getObject(1);
128 Assert.assertTrue(result instanceof PGbox3d);
129
130 // Test box2d if appropriate
131 if (postgisServerMajor < 1) {
132 logger.info("PostGIS version is too old, skipping box2ed test");
133 } else {
134 resultSet = statement.executeQuery("SELECT 'BOX(1 2,3 4)'::box2d");
135 resultSet.next();
136 result = (PGobject) resultSet.getObject(1);
137 Assert.assertTrue(result instanceof PGbox2d);
138 }
139 }
140 }
141
142
143 }
+0
-63
jdbc/src/test/java/org/postgis/DatatypesTest.java less more
0 /*
1 * DatatypesTest.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - example and test classes
4 *
5 * (C) 2004 Paul Ramsey, pramsey@refractions.net
6 *
7 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
8 *
9 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 */
26
27 package org.postgis;
28
29
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32 import org.testng.annotations.Test;
33
34 import java.sql.SQLException;
35
36
37 public class DatatypesTest {
38
39 private static final Logger logger = LoggerFactory.getLogger(DatatypesTest.class);
40
41 private static final String mlng_str = "MULTILINESTRING ((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))";
42
43
44 @Test
45 public void testPGgeometry() throws SQLException {
46 logger.trace("void testPGgeometry()");
47 logger.info(mlng_str);
48 PGgeometry pgf = new PGgeometry(mlng_str);
49 logger.info(pgf.toString());
50 }
51
52
53 @Test
54 public void testPGgeography() throws SQLException {
55 logger.trace("void testPGgeography()");
56 logger.info(mlng_str);
57 PGgeography pgf = new PGgeography(mlng_str);
58 logger.info(pgf.toString());
59 }
60
61
62 }
+0
-143
jdbc/src/test/java/org/postgis/EmptyGeometriesTest.java less more
0 /*
1 * EmptyGeometriesTest.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - example and test classes
4 *
5 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 *
21 */
22
23 package org.postgis;
24
25
26 import net.postgis.tools.testutils.TestContainerController;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
29 import org.testng.Assert;
30 import org.testng.ITestContext;
31 import org.testng.annotations.AfterClass;
32 import org.testng.annotations.BeforeClass;
33 import org.testng.annotations.Test;
34
35 import java.sql.*;
36 import java.util.ArrayList;
37 import java.util.List;
38
39
40 /**
41 * This class contains tests for handling of empty geometries.
42 *
43 * @author Phillip Ross {@literal <phillip.r.g.ross@gmail.com>}
44 */
45 public class EmptyGeometriesTest {
46
47 private static final Logger logger = LoggerFactory.getLogger(EmptyGeometriesTest.class);
48
49 private static final String DRIVER_WRAPPER_CLASS_NAME = "org.postgis.DriverWrapper";
50
51 private static final String DRIVER_WRAPPER_AUTOPROBE_CLASS_NAME = "org.postgis.DriverWrapperAutoprobe";
52
53
54 public static final String[] geometriesToTest = new String[] {
55 "POINT",
56 "LINESTRING",
57 "POLYGON",
58 "MULTIPOINT",
59 "MULTILINESTRING",
60 "MULTIPOLYGON",
61 "GEOMETRYCOLLECTION",
62 };
63
64 public static final String[] castTypes = new String[] {
65 "bytea",
66 "text",
67 "geometry",
68 "geography"
69 };
70
71 private Connection connection = null;
72
73 private Statement statement = null;
74
75
76 @Test
77 public void testSqlStatements() throws SQLException {
78 for (String sqlStatement : generateSqlStatements()) {
79 logger.debug("**********");
80 logger.debug("* Executing sql statemnent => [{}]", sqlStatement);
81 logger.debug("**********");
82 try (PreparedStatement preparedStatement = connection.prepareStatement(sqlStatement);
83 ResultSet resultSet = preparedStatement.executeQuery()
84 ) {
85 resultSet.next();
86 for (int i = 1; i <= castTypes.length; i++) {
87 Object resultSetObject = resultSet.getObject(i);
88 logger.debug("returned resultSetObject {} => (class=[{}]) {}", i, resultSetObject.getClass().getName(), resultSetObject);
89 }
90 resultSet.close();
91 }
92 }
93 }
94
95
96 private List<String> generateSqlStatements() {
97 List<String> sqlStatementList = new ArrayList<>();
98 for (String geometry : geometriesToTest) {
99 StringBuilder stringBuilder = new StringBuilder("select ");
100 for (String castType : castTypes) {
101 stringBuilder.append("geometry_in('")
102 .append(geometry)
103 .append(" EMPTY')::")
104 .append(castType)
105 .append(", ");
106 }
107 String sqlStatement = stringBuilder.substring(0, stringBuilder.lastIndexOf(","));
108 logger.debug("generate sql statement: {}", sqlStatement);
109 sqlStatementList.add(sqlStatement);
110 }
111 return sqlStatementList;
112 }
113
114
115 @BeforeClass
116 public void initJdbcConnection(ITestContext ctx) throws Exception {
117 final String jdbcUrlSuffix = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_JDBC_URL_SUFFIX);
118 Assert.assertNotNull(jdbcUrlSuffix);
119 final String jdbcUrl = "jdbc:postgresql" + jdbcUrlSuffix;
120 final String jdbcUsername = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_USER_PARAM_NAME);
121 Assert.assertNotNull(jdbcUsername);
122 final String jdbcPassword = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_PW_PARAM_NAME);
123 Assert.assertNotNull(jdbcPassword);
124 Class.forName(DRIVER_WRAPPER_CLASS_NAME);
125 Class.forName(DRIVER_WRAPPER_AUTOPROBE_CLASS_NAME);
126 connection = DriverManager.getConnection(jdbcUrl, jdbcUsername, jdbcPassword);
127 statement = connection.createStatement();
128 }
129
130
131 @AfterClass
132 public void unallocateDatabaseResources() throws Exception {
133 if ((statement != null) && (!statement.isClosed())) {
134 statement.close();
135 }
136 if ((connection != null) && (!connection.isClosed())) {
137 connection.close();
138 }
139 }
140
141
142 }
+0
-260
jdbc/src/test/java/org/postgis/GeographyDatatypeTest.java less more
0 /*
1 * This library is free software; you can redistribute it and/or
2 * modify it under the terms of the GNU Lesser General Public
3 * License as published by the Free Software Foundation; either
4 * version 2.1 of the License, or (at your option) any later version.
5 *
6 * This library is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 * Lesser General Public License for more details.
10 *
11 * You should have received a copy of the GNU Lesser General Public
12 * License along with this library; if not, write to the Free Software
13 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
14 *
15 * (C) 2020 Phillip Ross, phillip.w.g.ross@gmail.com
16 */
17
18 package org.postgis;
19
20
21 import net.postgis.tools.testutils.TestContainerController;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
24 import org.testng.Assert;
25 import org.testng.ITestContext;
26 import org.testng.annotations.AfterMethod;
27 import org.testng.annotations.BeforeMethod;
28 import org.testng.annotations.Test;
29
30 import java.sql.Connection;
31 import java.sql.DatabaseMetaData;
32 import java.sql.DriverManager;
33 import java.sql.PreparedStatement;
34 import java.sql.ResultSet;
35 import java.sql.Statement;
36 import java.util.UUID;
37
38
39 /**
40 * Integration tests for PGgeography.
41 *
42 * @author Phillip Ross
43 */
44 public class GeographyDatatypeTest {
45
46 /** The static logger instance. */
47 private static final Logger logger = LoggerFactory.getLogger(GeographyDatatypeTest.class);
48
49 /** The jdbc url prefix containing the jdbc protocol to be used for tests. */
50 private static final String JDBC_URL_PROTOCOL_PREFIX = "jdbc:postgresql";
51
52 /** The jdbc url prefix containing the jdbc lightweight protocol to be used for tests. */
53 private static final String JDBC_URL_LW_PROTOCOL_PREFIX = "jdbc:postgresql_lwgis";
54
55 /** The prefix for database tables used in the tests. */
56 private static final String DATABASE_TABLE_NAME_PREFIX = "jdbc_test";
57
58 /** Test geometries dataset. */
59 public static final String[] testGeometries = new String[] {
60 "POINT(10 10)", // 2D
61 "POINT(10 10 0)", // 3D with 3rd coordinate set to 0
62 "POINT(10 10 20)", // 3D
63 "POINT(1e100 1.2345e-100 -2e-5)", // 3D with scientific notation
64 "POINTM(10 10 20)", // 2D + Measures
65 "POINT(10 10 20 30)", // 3D + Measures
66 "MULTIPOINT(11 12, 20 20)", // broken format, see http://lists.jump-project.org/pipermail/jts-devel/2006-April/001572.html
67 "MULTIPOINT(11 12 13, 20 20 20)", // broken format
68 "MULTIPOINTM(11 12 13, 20 20 20)", // broken format
69 "MULTIPOINT(11 12 13 14,20 20 20 20)", // broken format
70 "MULTIPOINT((11 12), (20 20))", // OGC conforming format
71 "MULTIPOINT((11 12 13), (20 20 20))",
72 "MULTIPOINTM((11 12 13), (20 20 20))",
73 "MULTIPOINT((11 12 13 14),(20 20 20 20))",
74 "LINESTRING(10 10,20 20,50 50,34 34)",
75 "LINESTRING(10 10 20,20 20 20,50 50 50,34 34 34)",
76 "LINESTRINGM(10 10 20,20 20 20,50 50 50,34 34 34)",
77 "LINESTRING(10 10 20 20,20 20 20 20,50 50 50 50,34 34 34 50)",
78 "POLYGON((10 10,20 10,20 20,20 10,10 10),(5 5,5 6,6 6,6 5,5 5))",
79 "POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))",
80 "POLYGONM((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))",
81 "POLYGON((10 10 0 7,20 10 0 7,20 20 0 7,20 10 0 7,10 10 0 7),(5 5 0 7,5 6 0 7,6 6 0 7,6 5 0 7,5 5 0 7))",
82 "MULTIPOLYGON(((10 10,20 10,20 20,20 10,10 10),(5 5,5 6,6 6,6 5,5 5)),((10 10,20 10,20 20,20 10,10 10),(5 5,5 6,6 6,6 5,5 5)))",
83 "MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))",
84 "MULTIPOLYGONM(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))",
85 "MULTIPOLYGON(((10 10 0 7,20 10 0 7,20 20 0 7,20 10 0 7,10 10 0 7),(5 5 0 7,5 6 0 7,6 6 0 7,6 5 0 7,5 5 0 7)),((10 10 0 7,20 10 0 7,20 20 0 7,20 10 0 7,10 10 0 7),(5 5 0 7,5 6 0 7,6 6 0 7,6 5 0 7,5 5 0 7)))",
86 "MULTILINESTRING((10 10,20 10,20 20,20 10,10 10),(5 5,5 6,6 6,6 5,5 5))",
87 "MULTILINESTRING((10 10 5,20 10 5,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))",
88 "MULTILINESTRINGM((10 10 7,20 10 7,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))",
89 "MULTILINESTRING((10 10 0 7,20 10 0 7,20 20 0 7,20 10 0 7,10 10 0 7),(5 5 0 7,5 6 0 7,6 6 0 7,6 5 0 7,5 5 0 7))",
90 "GEOMETRYCOLLECTION(POINT(10 10),POINT(20 20))",
91 "GEOMETRYCOLLECTION(POINT(10 10 20),POINT(20 20 20))",
92 "GEOMETRYCOLLECTION(POINT(10 10 20 7),POINT(20 20 20 7))",
93 "GEOMETRYCOLLECTION(LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34),LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34))",
94 "GEOMETRYCOLLECTION(POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))",
95 "GEOMETRYCOLLECTION(MULTIPOINT(10 10 10, 20 20 20),MULTIPOINT(10 10 10, 20 20 20))", // Cannot be parsed by 0.X servers, broken format
96 "GEOMETRYCOLLECTION(MULTIPOINT((10 10 10), (20 20 20)),MULTIPOINT((10 10 10), (20 20 20)))", // Cannot be parsed by 0.X servers, OGC conformant
97 "GEOMETRYCOLLECTION(MULTILINESTRING((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))", // PostGIs 0.X "flattens" this geometry, so it is not equal after reparsing.
98 "GEOMETRYCOLLECTION(MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))),MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))))", // PostGIs 0.X "flattens" this geometry, so it is not equal after reparsing.
99 "GEOMETRYCOLLECTION(POINT(10 10 20),LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34),POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))",
100 "GEOMETRYCOLLECTION(POINT(10 10 20),MULTIPOINT(10 10 10, 20 20 20),LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34),POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))),MULTILINESTRING((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))", // Collections that contain both X and MultiX do not work on PostGIS 0.x, broken format
101 "GEOMETRYCOLLECTION(POINT(10 10 20),MULTIPOINT((10 10 10), (20 20 20)),LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34),POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))),MULTILINESTRING((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))", // Collections that contain both X and MultiX do not work on PostGIS 0.x, OGC conformant
102 "GEOMETRYCOLLECTION EMPTY", // new (correct) representation
103 "GEOMETRYCOLLECTIONM(POINTM(10 10 20),POINTM(20 20 20))"
104 };
105
106 /** The JDBC Connection to be used for tests. */
107 private Connection connection = null;
108
109 /** The JDBC Connection w/ lightweight protocol to be used for tests. */
110 private Connection connectionLW = null;
111
112
113 /**
114 * Initializes a new JDBC Connection.
115 *
116 * @param ctx the test context
117 * @throws Exception when an exception occurs
118 */
119 @BeforeMethod
120 public void initJdbcConnection(ITestContext ctx) throws Exception {
121 final String jdbcUrlSuffix = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_JDBC_URL_SUFFIX);
122 Assert.assertNotNull(jdbcUrlSuffix);
123 final String jdbcUrl = JDBC_URL_PROTOCOL_PREFIX + jdbcUrlSuffix;
124 final String jdbcUrlLW = JDBC_URL_LW_PROTOCOL_PREFIX + jdbcUrlSuffix;
125 final String jdbcUsername = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_USER_PARAM_NAME);
126 Assert.assertNotNull(jdbcUsername);
127 final String jdbcPassword = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_PW_PARAM_NAME);
128 Assert.assertNotNull(jdbcPassword);
129 Class.forName("org.postgis.DriverWrapperLW");
130 connection = DriverManager.getConnection(jdbcUrl, jdbcUsername, jdbcPassword);
131 connectionLW = DriverManager.getConnection(jdbcUrlLW, jdbcUsername, jdbcPassword);
132 }
133
134
135 /**
136 * Un-allocates the JDBC connection.
137 *
138 * @throws Exception when an exception occurs
139 */
140 @AfterMethod
141 public void unallocateDatabaseResources() throws Exception {
142 if ((connection != null) && (!connection.isClosed())) {
143 connection.close();
144 }
145 if ((connectionLW != null) && (!connectionLW.isClosed())) {
146 connection.close();
147 }
148 }
149
150
151 /**
152 * Test inserting geometries into the database with prepared statements and querying back the results with
153 * both geometry/geography and standard/lightweight.
154 *
155 * @throws Exception when an exception occurs.
156 */
157 @Test
158 public void testDatatypes() throws Exception {
159
160 final String testTableName = DATABASE_TABLE_NAME_PREFIX
161 + "_"
162 + UUID.randomUUID()
163 .toString()
164 .replaceAll("-", "");
165
166 final String dropTableSQL = "drop table " + testTableName;
167
168 final String createTableSQL = "create table " + testTableName
169 + " ( _id numeric,"
170 + " geometry_value geometry, geometrylw_value geometry,"
171 + " geography_value geography, geographylw_value geography)";
172 final int idColumnIndex = 1;
173 final int geometryValueColumnIndex = 2;
174 final int geometrylwValueColumnIndex = 3;
175 final int geographyValueColumnIndex = 4;
176 final int geographylwValueColumnIndex = 5;
177
178 final String insertSQL = "insert into " + testTableName + " ( "
179 + "_id, geometry_value, geometrylw_value, "
180 + "geography_value, geographylw_value) "
181 + "values ( ?, ?, ?, ?, ? )";
182
183 boolean tableExists = false;
184 DatabaseMetaData databaseMetaData = connection.getMetaData();
185 try (
186 ResultSet resultSet = databaseMetaData.getTables(
187 null, null, testTableName.toLowerCase(), new String[] { "TABLE" }
188 )
189 ) {
190 while (resultSet.next()) {
191 tableExists = true;
192 }
193 }
194
195 if (tableExists) {
196 logger.debug("Dropping pre-existing test table...");
197 try (Statement statement = connection.createStatement()) {
198 statement.executeQuery(dropTableSQL);
199 }
200 }
201
202 logger.debug("Creating test table...");
203 try (Statement statement = connection.createStatement()) {
204 statement.execute(createTableSQL);
205 }
206
207
208 logger.debug("Inserting test geometries into table...");
209 try (PreparedStatement preparedStatement = connection.prepareStatement(insertSQL)) {
210 for (int i = 0; i < testGeometries.length; i++) {
211 PGgeometry geometry = new PGgeometry(testGeometries[i]);
212 PGgeometryLW geometryLW = new PGgeometryLW(testGeometries[i]);
213 PGgeography geography = new PGgeography(testGeometries[i]);
214 PGgeographyLW geographyLW = new PGgeographyLW(testGeometries[i]);
215
216 preparedStatement.setInt(idColumnIndex, i);
217 preparedStatement.setObject(geometryValueColumnIndex, geometry);
218 preparedStatement.setObject(geometrylwValueColumnIndex, geometryLW);
219 preparedStatement.setObject(geographyValueColumnIndex, geography);
220 preparedStatement.setObject(geographylwValueColumnIndex, geographyLW);
221 preparedStatement.executeUpdate();
222 }
223 }
224
225 logger.debug("Querying table with standard connection...");
226 try (
227 Statement statement = connection.createStatement();
228 ResultSet resultSet = statement.executeQuery(
229 "select _id, geometry_value, geometrylw_value, geography_value, geographylw_value from "
230 + testTableName
231 )
232 ) {
233 while (resultSet.next()) {
234 Assert.assertEquals(resultSet.getObject(geometryValueColumnIndex).getClass(), PGgeometry.class);
235 Assert.assertEquals(resultSet.getObject(geometrylwValueColumnIndex).getClass(), PGgeometry.class);
236 Assert.assertEquals(resultSet.getObject(geographyValueColumnIndex).getClass(), PGgeography.class);
237 Assert.assertEquals(resultSet.getObject(geographylwValueColumnIndex).getClass(), PGgeography.class);
238 }
239 }
240
241 logger.debug("Querying table with lightweight connection...");
242 try (
243 Statement statement = connectionLW.createStatement();
244 ResultSet resultSet = statement.executeQuery(
245 "select _id, geometry_value, geometrylw_value, geography_value, geographylw_value from "
246 + testTableName
247 )
248 ) {
249 while (resultSet.next()) {
250 Assert.assertEquals(resultSet.getObject(geometryValueColumnIndex).getClass(), PGgeometryLW.class);
251 Assert.assertEquals(resultSet.getObject(geometrylwValueColumnIndex).getClass(), PGgeometryLW.class);
252 Assert.assertEquals(resultSet.getObject(geographyValueColumnIndex).getClass(), PGgeographyLW.class);
253 Assert.assertEquals(resultSet.getObject(geographylwValueColumnIndex).getClass(), PGgeographyLW.class);
254 }
255 }
256 }
257
258
259 }
+0
-475
jdbc/src/test/java/org/postgis/ParserTest.java less more
0 /*
1 * ParserTest.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - example and test classes
4 *
5 * (C) 2004 Paul Ramsey, pramsey@refractions.net
6 *
7 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
8 *
9 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 */
26
27 package org.postgis;
28
29
30 import org.postgis.binary.BinaryParser;
31 import org.postgis.binary.BinaryWriter;
32 import org.postgis.binary.ValueSetter;
33 import net.postgis.tools.testutils.TestContainerController;
34 import org.postgis.util.VersionUtil;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37 import org.testng.Assert;
38 import org.testng.ITestContext;
39 import org.testng.annotations.AfterClass;
40 import org.testng.annotations.BeforeClass;
41 import org.testng.annotations.Test;
42
43 import java.sql.Connection;
44 import java.sql.DriverManager;
45 import java.sql.PreparedStatement;
46 import java.sql.ResultSet;
47 import java.sql.SQLException;
48 import java.sql.Statement;
49 import java.sql.Types;
50 import java.util.Objects;
51
52
53 public class ParserTest {
54
55 private static final Logger logger = LoggerFactory.getLogger(ParserTest.class);
56
57 private static final String DRIVER_WRAPPER_CLASS_NAME = "org.postgis.DriverWrapper";
58
59 private static final String DRIVER_WRAPPER_AUTOPROBE_CLASS_NAME = "org.postgis.DriverWrapperAutoprobe";
60
61 /** The srid we use for the srid tests */
62 public static final int SRID = 4326;
63
64 /** The string prefix we get for the srid tests */
65 public static final String SRIDPREFIX = "SRID=" + SRID + ";";
66
67 /**
68 * Our set of geometries to test.
69 */
70 public static final String ALL = "ALL";
71 public static final String ONLY10 = "ONLY10";
72 public static final String EQUAL10 = "EQUAL10";
73 public static final String[][] testset = new String[][]{
74 {
75 ALL, // 2D
76 "POINT(10 10)"},
77 {
78 ALL, // 3D with 3rd coordinate set to 0
79 "POINT(10 10 0)"},
80 {
81 ALL, // 3D
82 "POINT(10 10 20)"},
83 {
84 ALL, // 3D with scientific notation
85 "POINT(1e100 1.2345e-100 -2e-5)"},
86 {
87 ONLY10, // 2D + Measures
88 "POINTM(10 10 20)"},
89 {
90 ONLY10, // 3D + Measures
91 "POINT(10 10 20 30)"},
92 {
93 ALL, // broken format, see http://lists.jump-project.org/pipermail/jts-devel/2006-April/001572.html
94 "MULTIPOINT(11 12, 20 20)"},
95 {
96 ALL,// broken format
97 "MULTIPOINT(11 12 13, 20 20 20)"},
98 {
99 ONLY10,// broken format
100 "MULTIPOINTM(11 12 13, 20 20 20)"},
101 {
102 ONLY10,// broken format
103 "MULTIPOINT(11 12 13 14,20 20 20 20)"},
104 {
105 ALL, // OGC conforming format
106 "MULTIPOINT((11 12), (20 20))"},
107 {
108 ALL,
109 "MULTIPOINT((11 12 13), (20 20 20))"},
110 {
111 ONLY10,
112 "MULTIPOINTM((11 12 13), (20 20 20))"},
113 {
114 ONLY10,
115 "MULTIPOINT((11 12 13 14),(20 20 20 20))"},
116 {
117 ALL,
118 "LINESTRING(10 10,20 20,50 50,34 34)"},
119 {
120 ALL,
121 "LINESTRING(10 10 20,20 20 20,50 50 50,34 34 34)"},
122 {
123 ONLY10,
124 "LINESTRINGM(10 10 20,20 20 20,50 50 50,34 34 34)"},
125 {
126 ONLY10,
127 "LINESTRING(10 10 20 20,20 20 20 20,50 50 50 50,34 34 34 50)"},
128 {
129 ALL,
130 "POLYGON((10 10,20 10,20 20,20 10,10 10),(5 5,5 6,6 6,6 5,5 5))"},
131 {
132 ALL,
133 "POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))"},
134 {
135 ONLY10,
136 "POLYGONM((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))"},
137 {
138 ONLY10,
139 "POLYGON((10 10 0 7,20 10 0 7,20 20 0 7,20 10 0 7,10 10 0 7),(5 5 0 7,5 6 0 7,6 6 0 7,6 5 0 7,5 5 0 7))"},
140 {
141 ALL,
142 "MULTIPOLYGON(((10 10,20 10,20 20,20 10,10 10),(5 5,5 6,6 6,6 5,5 5)),((10 10,20 10,20 20,20 10,10 10),(5 5,5 6,6 6,6 5,5 5)))"},
143 {
144 ALL,
145 "MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))"},
146 {
147 ONLY10,
148 "MULTIPOLYGONM(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))"},
149 {
150 ONLY10,
151 "MULTIPOLYGON(((10 10 0 7,20 10 0 7,20 20 0 7,20 10 0 7,10 10 0 7),(5 5 0 7,5 6 0 7,6 6 0 7,6 5 0 7,5 5 0 7)),((10 10 0 7,20 10 0 7,20 20 0 7,20 10 0 7,10 10 0 7),(5 5 0 7,5 6 0 7,6 6 0 7,6 5 0 7,5 5 0 7)))"},
152 {
153 ALL,
154 "MULTILINESTRING((10 10,20 10,20 20,20 10,10 10),(5 5,5 6,6 6,6 5,5 5))"},
155 {
156 ALL,
157 "MULTILINESTRING((10 10 5,20 10 5,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))"},
158 {
159 ONLY10,
160 "MULTILINESTRINGM((10 10 7,20 10 7,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))"},
161 {
162 ONLY10,
163 "MULTILINESTRING((10 10 0 7,20 10 0 7,20 20 0 7,20 10 0 7,10 10 0 7),(5 5 0 7,5 6 0 7,6 6 0 7,6 5 0 7,5 5 0 7))"},
164 {
165 ALL,
166 "GEOMETRYCOLLECTION(POINT(10 10),POINT(20 20))"},
167 {
168 ALL,
169 "GEOMETRYCOLLECTION(POINT(10 10 20),POINT(20 20 20))"},
170 {
171 ONLY10,
172 "GEOMETRYCOLLECTION(POINT(10 10 20 7),POINT(20 20 20 7))"},
173 {
174 ALL,
175 "GEOMETRYCOLLECTION(LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34),LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34))"},
176 {
177 ALL,
178 "GEOMETRYCOLLECTION(POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))"},
179 {
180 ONLY10, // Cannot be parsed by 0.X servers, broken format
181 "GEOMETRYCOLLECTION(MULTIPOINT(10 10 10, 20 20 20),MULTIPOINT(10 10 10, 20 20 20))"},
182 {
183 ONLY10, // Cannot be parsed by 0.X servers, OGC conformant
184 "GEOMETRYCOLLECTION(MULTIPOINT((10 10 10), (20 20 20)),MULTIPOINT((10 10 10), (20 20 20)))"},
185 {
186 EQUAL10, // PostGIs 0.X "flattens" this geometry, so it is not
187 // equal after reparsing.
188 "GEOMETRYCOLLECTION(MULTILINESTRING((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))"},
189 {
190 EQUAL10,// PostGIs 0.X "flattens" this geometry, so it is not equal
191 // after reparsing.
192 "GEOMETRYCOLLECTION(MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))),MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))))"},
193 {
194 ALL,
195 "GEOMETRYCOLLECTION(POINT(10 10 20),LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34),POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))"},
196 {
197 ONLY10, // Collections that contain both X and MultiX do not work on
198 // PostGIS 0.x, broken format
199 "GEOMETRYCOLLECTION(POINT(10 10 20),MULTIPOINT(10 10 10, 20 20 20),LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34),POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))),MULTILINESTRING((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))"},
200 {
201 ONLY10, // Collections that contain both X and MultiX do not work on
202 // PostGIS 0.x, OGC conformant
203 "GEOMETRYCOLLECTION(POINT(10 10 20),MULTIPOINT((10 10 10), (20 20 20)),LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34),POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))),MULTILINESTRING((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))"},
204 {
205 ALL,// new (correct) representation
206 "GEOMETRYCOLLECTION EMPTY"},
207 {
208 ALL,
209 "GEOMETRYCOLLECTIONM(POINTM(10 10 20),POINTM(20 20 20))"},
210 // end
211 };
212
213 public static final String[][] testSetNonWorking = new String[][]{
214 {
215 ALL, // Old (bad) PostGIS 0.X Representation
216 "GEOMETRYCOLLECTION(EMPTY)"},
217 {
218 ONLY10,// new (correct) representation - does not work on 0.X
219 "POINT EMPTY"},
220 {
221 ONLY10,// new (correct) representation - does not work on 0.X
222 "LINESTRING EMPTY"},
223 {
224 ONLY10,// new (correct) representation - does not work on 0.X
225 "POLYGON EMPTY"},
226 {
227 ONLY10,// new (correct) representation - does not work on 0.X
228 "MULTIPOINT EMPTY"},
229 {
230 ONLY10,// new (correct) representation - does not work on 0.X
231 "MULTILINESTRING EMPTY"},
232 {
233 ONLY10,// new (correct) representation - does not work on 0.X
234 "MULTIPOLYGON EMPTY"}
235 };
236
237 private static BinaryParser binaryParser = new BinaryParser();
238
239 private static final BinaryWriter binaryWriter = new BinaryWriter();
240
241 private Connection connection = null;
242
243 private Statement statement = null;
244
245
246 @Test
247 public void testParser() throws Exception {
248 for (String[] aTestset : testset) {
249 test(aTestset[1], aTestset[0]);
250 test(SRIDPREFIX + aTestset[1], aTestset[0]);
251 }
252 }
253
254
255 public void test(String WKT, String flags) throws SQLException {
256 logger.debug("Original: {} ", WKT);
257 Geometry geom = GeometryBuilder.geomFromString(WKT);
258 String parsed = geom.toString();
259 logger.debug("Parsed: {}", parsed);
260 Geometry regeom = GeometryBuilder.geomFromString(parsed);
261 String reparsed = regeom.toString();
262 logger.debug("Re-Parsed: {}", reparsed);
263 Assert.assertEquals(geom, regeom, "Geometries are not equal");
264 Assert.assertEquals(reparsed, parsed, "Text Reps are not equal");
265
266 String hexNWKT = binaryWriter.writeHexed(regeom, ValueSetter.NDR.NUMBER);
267 logger.debug("NDRHex: {}", hexNWKT);
268 regeom = GeometryBuilder.geomFromString(hexNWKT);
269 logger.debug("ReNDRHex: {}", regeom);
270 Assert.assertEquals(geom, regeom, "Geometries are not equal");
271
272 String hexXWKT = binaryWriter.writeHexed(regeom, ValueSetter.XDR.NUMBER);
273 logger.debug("XDRHex: {}", hexXWKT);
274 regeom = GeometryBuilder.geomFromString(hexXWKT);
275 logger.debug("ReXDRHex: {}", regeom);
276 Assert.assertEquals(geom, regeom, "Geometries are not equal");
277
278 byte[] NWKT = binaryWriter.writeBinary(regeom, ValueSetter.NDR.NUMBER);
279 regeom = binaryParser.parse(NWKT);
280 logger.debug("NDR: {}", regeom);
281 Assert.assertEquals(geom, regeom, "Geometries are not equal");
282
283 byte[] XWKT = binaryWriter.writeBinary(regeom, ValueSetter.XDR.NUMBER);
284 regeom = binaryParser.parse(XWKT);
285 logger.debug("XDR: {}", regeom);
286 Assert.assertEquals(geom, regeom, "Geometries are not equal");
287
288 final String postGISVersionString = VersionUtil.retrievePostGISServerVersionString(connection);
289 logger.debug("postGISVersionString: {}", postGISVersionString);
290 final String postGISMajorVersion = VersionUtil.retrievePostGISServerMajorVersion(connection);
291 logger.debug("postGISMajorVersion: {}", postGISMajorVersion);
292 final String postGISMinorVersion = VersionUtil.retrievePostGISServerMinorVersion(connection);
293 logger.debug("postGISMinorVersion: {}", postGISMinorVersion);
294
295 int serverPostgisMajor = 0;
296 try {
297 serverPostgisMajor = Integer.parseInt(postGISMajorVersion);
298 } catch (NumberFormatException nfe) {
299 logger.error("Caught a number format exception attempting to parse PostGIS Server Major Version");
300 }
301
302 if ((Objects.equals(flags, ONLY10)) && serverPostgisMajor < 1) {
303 logger.info("PostGIS server too old, skipping test on database connection {}", connection.getCatalog());
304 } else {
305 logger.debug("Testing on connection {}", connection.getCatalog());
306
307 Geometry sqlGeom = viaSQL(WKT);
308 logger.debug("SQLin: {}", sqlGeom);
309 if (!geom.equals(sqlGeom)) {
310 logger.warn("Geometries after SQL are not equal");
311 if (Objects.equals(flags, EQUAL10) && serverPostgisMajor < 1) {
312 logger.info("This is expected with PostGIS {}.X", serverPostgisMajor);
313 } else {
314 Assert.fail();
315 }
316 }
317
318 Geometry sqlreGeom = viaSQL(parsed);
319 logger.debug("SQLout: {}", sqlreGeom);
320 if (!geom.equals(sqlreGeom)) {
321 logger.warn("Reparsed Geometries after SQL are not equal!");
322 if (Objects.equals(flags, EQUAL10) && serverPostgisMajor < 1) {
323 logger.info("This is expected with PostGIS {}.X", serverPostgisMajor);
324 } else {
325 Assert.fail();
326 }
327 }
328
329 sqlreGeom = viaPrepSQL(geom, connection);
330 logger.debug("Prepared: {}", sqlreGeom.toString());
331 if (!geom.equals(sqlreGeom)) {
332 logger.warn("Reparsed Geometries after prepared StatementSQL are not equal!");
333 if (Objects.equals(flags, EQUAL10) && serverPostgisMajor < 1) {
334 logger.info("This is expected with PostGIS {}.X", serverPostgisMajor);
335 } else {
336 Assert.fail();
337 }
338 }
339
340 /*
341 // Temporarily removing this check since it breaks between PostGIS v2.4.4 and PostGIS v2.5.0
342 // Tests performed via psql between mdillon/postgis:9.3 and mdillon/postgis:9.4 shows the breakage
343 // Test is also broken in mdillon/postgis:11-alpine
344 // In psql, the sql statement "SELECT ST_AsEWKT(geometry_in('POINT(1e100 1.2345e-100 -2e-5)'));" returns
345 // "POINT(1e+100 1.2345e-100 -2e-05)" with 9.3 and "POINT(1e+100 0 -0.00002)" with 9.4 and later
346
347 // asEWKT() function is not present on PostGIS 0.X, and the test
348 // is pointless as 0.X uses EWKT as canonical rep so the same
349 // functionality was already tested above.
350 if (serverPostgisMajor >= 1) {
351 sqlGeom = ewktViaSQL(WKT, statement);
352 logger.debug("asEWKT: {}", sqlGeom);
353 Assert.assertEquals(geom, sqlGeom);
354 }
355 */
356
357 // asEWKB() function is not present on PostGIS 0.X.
358 if (serverPostgisMajor >= 1) {
359 sqlGeom = ewkbViaSQL(WKT, statement);
360 logger.debug("asEWKB: {}", sqlGeom);
361 Assert.assertEquals(geom, sqlGeom);
362 }
363
364 // HexEWKB parsing is not present on PostGIS 0.X.
365 if (serverPostgisMajor >= 1) {
366 sqlGeom = viaSQL(hexNWKT);
367 logger.debug("hexNWKT: {}", sqlGeom);
368 Assert.assertEquals(geom, sqlGeom);
369 }
370
371 if (serverPostgisMajor >= 1) {
372 sqlGeom = viaSQL(hexXWKT);
373 logger.debug("hexXWKT: {}", sqlGeom);
374 Assert.assertEquals(geom, sqlGeom);
375 }
376
377 // Canonical binary input is not present before 1.0
378 if (serverPostgisMajor >= 1) {
379 sqlGeom = binaryViaSQL(NWKT, connection);
380 logger.debug("NWKT: {}", sqlGeom);
381 Assert.assertEquals(geom, sqlGeom);
382 }
383
384 if (serverPostgisMajor >= 1) {
385 sqlGeom = binaryViaSQL(XWKT, connection);
386 logger.debug("XWKT: {}", sqlGeom);
387 Assert.assertEquals(geom, sqlGeom);
388 }
389 }
390 }
391
392
393 /** Pass a geometry representation through the SQL server */
394 private Geometry viaSQL(String rep) throws SQLException {
395 logger.trace("Geometry viaSQL(String rep)");
396 logger.trace("[P] rep => {}", rep);
397 ResultSet resultSet = statement.executeQuery("SELECT geometry_in('" + rep + "')");
398 resultSet.next();
399 return ((PGgeometry) resultSet.getObject(1)).getGeometry();
400 }
401
402
403 /**
404 * Pass a geometry representation through the SQL server via prepared
405 * statement
406 */
407 private static Geometry viaPrepSQL(Geometry geom, Connection conn) throws SQLException {
408 PreparedStatement preparedStatement = conn.prepareStatement("SELECT ?::geometry");
409 PGgeometry wrapper = new PGgeometry(geom);
410 preparedStatement.setObject(1, wrapper, Types.OTHER);
411 ResultSet resultSet = preparedStatement.executeQuery();
412 resultSet.next();
413 PGgeometry resultwrapper = (PGgeometry)resultSet.getObject(1);
414 return resultwrapper.getGeometry();
415 }
416
417
418 /** Pass a geometry representation through the SQL server via EWKT */
419 private static Geometry ewktViaSQL(String rep, Statement stat) throws SQLException {
420 ResultSet resultSet = stat.executeQuery("SELECT ST_AsEWKT(geometry_in('" + rep + "'))");
421 resultSet.next();
422 String resrep = resultSet.getString(1);
423 return GeometryBuilder.geomFromString(resrep);
424 }
425
426
427 /** Pass a geometry representation through the SQL server via EWKB */
428 private static Geometry ewkbViaSQL(String rep, Statement stat) throws SQLException {
429 ResultSet resultSet = stat.executeQuery("SELECT ST_AsEWKB(geometry_in('" + rep + "'))");
430 resultSet.next();
431 byte[] resrep = resultSet.getBytes(1);
432 return binaryParser.parse(resrep);
433 }
434
435
436 /** Pass a EWKB geometry representation through the server */
437 private static Geometry binaryViaSQL(byte[] rep, Connection conn) throws SQLException {
438 PreparedStatement preparedStatement = conn.prepareStatement("SELECT ?::bytea::geometry");
439 preparedStatement.setBytes(1, rep);
440 ResultSet resultSet = preparedStatement.executeQuery();
441 resultSet.next();
442 PGgeometry resultwrapper = ((PGgeometry) resultSet.getObject(1));
443 return resultwrapper.getGeometry();
444 }
445
446
447 @BeforeClass
448 public void initJdbcConnection(ITestContext ctx) throws Exception {
449 final String jdbcUrlSuffix = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_JDBC_URL_SUFFIX);
450 Assert.assertNotNull(jdbcUrlSuffix);
451 final String jdbcUrl = "jdbc:postgresql" + jdbcUrlSuffix;
452 final String jdbcUsername = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_USER_PARAM_NAME);
453 Assert.assertNotNull(jdbcUsername);
454 final String jdbcPassword = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_PW_PARAM_NAME);
455 Assert.assertNotNull(jdbcPassword);
456 Class.forName(DRIVER_WRAPPER_CLASS_NAME);
457 Class.forName(DRIVER_WRAPPER_AUTOPROBE_CLASS_NAME);
458 connection = DriverManager.getConnection(jdbcUrl, jdbcUsername, jdbcPassword);
459 statement = connection.createStatement();
460 }
461
462
463 @AfterClass
464 public void unallocateDatabaseResources() throws Exception {
465 if ((statement != null) && (!statement.isClosed())) {
466 statement.close();
467 }
468 if ((connection != null) && (!connection.isClosed())) {
469 connection.close();
470 }
471 }
472
473
474 }
+0
-54
jdbc/src/test/java/org/postgis/SerializationTest.java less more
0 /*
1 * ServerTest.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - example and test classes
4 *
5 * (C) 2004 Paul Ramsey, pramsey@refractions.net
6 *
7 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
8 *
9 * (C) 2017 Phillip Ross, phillip.w.g.ross@gmail.com
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 */
26
27 package org.postgis;
28
29
30 import org.testng.Assert;
31 import org.testng.annotations.Test;
32
33 import java.io.ByteArrayOutputStream;
34 import java.io.NotSerializableException;
35 import java.io.ObjectOutputStream;
36
37
38 public class SerializationTest {
39
40
41 @Test
42 public void serializationCheckPGgeometry() throws Exception {
43 try {
44 new ObjectOutputStream(new ByteArrayOutputStream())
45 .writeObject(new PGgeometry("MULTIPOLYGON(((1 1,1 2,2 1,1 1)))"));
46 }
47 catch (NotSerializableException ex) {
48 Assert.fail("serialization of PGgeometry failed: " + ex);
49 }
50 }
51
52
53 }
+0
-126
jdbc/src/test/java/org/postgis/ServerTest.java less more
0 /*
1 * ServerTest.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - example and test classes
4 *
5 * (C) 2004 Paul Ramsey, pramsey@refractions.net
6 *
7 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
8 *
9 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 */
26
27 package org.postgis;
28
29
30 import net.postgis.tools.testutils.TestContainerController;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33 import org.testng.Assert;
34 import org.testng.ITestContext;
35 import org.testng.annotations.AfterClass;
36 import org.testng.annotations.BeforeClass;
37 import org.testng.annotations.Test;
38
39 import java.sql.*;
40 import java.util.UUID;
41
42
43 public class ServerTest {
44
45 private static final Logger logger = LoggerFactory.getLogger(ServerTest.class);
46
47 private static final String JDBC_DRIVER_CLASS_NAME = "org.postgresql.Driver";
48
49 private static final String DATABASE_TABLE_NAME_PREFIX = "jdbc_test";
50
51 private Connection connection = null;
52
53 private Statement statement = null;
54
55
56 @Test
57 public void testServer() throws Exception {
58 String dbtable = DATABASE_TABLE_NAME_PREFIX + "_" + UUID.randomUUID().toString().replaceAll("-", "");
59
60 String dropSQL = "drop table " + dbtable;
61 String createSQL = "create table " + dbtable + " (geom geometry, id int4)";
62 String insertPointSQL = "insert into " + dbtable + " values ('POINT (10 10 10)',1)";
63 String insertPolygonSQL = "insert into " + dbtable + " values ('POLYGON ((0 0 0,0 10 0,10 10 0,10 0 0,0 0 0))',2)";
64
65 logger.debug("Adding geometric type entries...");
66 ((org.postgresql.PGConnection)connection).addDataType("geometry", PGgeometry.class);
67 ((org.postgresql.PGConnection)connection).addDataType("box3d", PGbox3d.class);
68
69 logger.debug("Creating table with geometric types...");
70 boolean tableExists = false;
71 DatabaseMetaData databaseMetaData = connection.getMetaData();
72 try (ResultSet resultSet = databaseMetaData.getTables(null, null, dbtable.toLowerCase(), new String[] {"TABLE"})) {
73 while (resultSet.next()) {
74 tableExists = true;
75 }
76 }
77 if (tableExists) {
78 statement.execute(dropSQL);
79 }
80 statement.execute(createSQL);
81
82 logger.debug("Inserting point...");
83 statement.execute(insertPointSQL);
84
85 logger.debug("Inserting polygon...");
86 statement.execute(insertPolygonSQL);
87
88 logger.debug("Querying table...");
89 ResultSet resultSet = statement.executeQuery("select ST_AsText(geom),id from " + dbtable);
90 while (resultSet.next()) {
91 Object obj = resultSet.getObject(1);
92 int id = resultSet.getInt(2);
93 logger.debug("Row {}: {}", id, obj.toString());
94 }
95
96 }
97
98
99 @BeforeClass
100 public void initJdbcConnection(ITestContext ctx) throws Exception {
101 final String jdbcUrlSuffix = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_JDBC_URL_SUFFIX);
102 Assert.assertNotNull(jdbcUrlSuffix);
103 final String jdbcUrl = "jdbc:postgresql" + jdbcUrlSuffix;
104 final String jdbcUsername = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_USER_PARAM_NAME);
105 Assert.assertNotNull(jdbcUsername);
106 final String jdbcPassword = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_PW_PARAM_NAME);
107 Assert.assertNotNull(jdbcPassword);
108 Class.forName(JDBC_DRIVER_CLASS_NAME);
109 connection = DriverManager.getConnection(jdbcUrl, jdbcUsername, jdbcPassword);
110 statement = connection.createStatement();
111 }
112
113
114 @AfterClass
115 public void unallocateDatabaseResources() throws Exception {
116 if ((statement != null) && (!statement.isClosed())) {
117 statement.close();
118 }
119 if ((connection != null) && (!connection.isClosed())) {
120 connection.close();
121 }
122 }
123
124
125 }
+0
-173
jdbc/src/test/java/org/postgis/VersionPrinter.java less more
0 /*
1 * VersionPrinter.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - example and test classes
4 *
5 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
6 *
7 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24
25 package org.postgis;
26
27
28 import net.postgis.tools.testutils.TestContainerController;
29 import org.postgresql.Driver;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32 import org.testng.Assert;
33 import org.testng.ITestContext;
34 import org.testng.annotations.AfterClass;
35 import org.testng.annotations.BeforeClass;
36 import org.testng.annotations.Test;
37
38 import java.sql.*;
39
40
41 /**
42 * Prints out as much version information as available.
43 */
44 public class VersionPrinter {
45
46 private static final Logger logger = LoggerFactory.getLogger(VersionPrinter.class);
47
48 private static final String JDBC_DRIVER_CLASS_NAME = "org.postgresql.Driver";
49
50 public static String[] POSTGIS_FUNCTIONS = {
51 "postgis_version",
52 "postgis_proj_version",
53 "postgis_scripts_installed",
54 "postgis_lib_version",
55 "postgis_scripts_released",
56 "postgis_uses_stats",
57 "postgis_geos_version",
58 "postgis_scripts_build_date",
59 "postgis_lib_build_date",
60 "postgis_full_version",
61 "postgis_gdal_version",
62 "postgis_libjson_version",
63 "postgis_libxml_version",
64 "postgis_raster_lib_version",
65 "postgis_svn_version"
66 };
67
68 private Connection connection = null;
69
70 private Statement statement = null;
71
72
73 @Test
74 public void test() throws Exception {
75
76 // Print PostGIS version
77 logger.info("*** PostGIS jdbc client code ***");
78 String fullVersion = Version.getFullVersion();
79 Assert.assertNotNull(fullVersion);
80 logger.info("\t getFullVersion: {}", fullVersion);
81
82 // Print PostgreSQL JDBC Versions
83 logger.info("*** PostgreSQL JDBC Driver ***");
84 String driverVersion = Driver.getVersion();
85 Assert.assertNotNull(driverVersion);
86 logger.info("\t getVersion: {}", driverVersion);
87
88 try {
89 Driver driver = new Driver();
90 int majorVersion = driver.getMajorVersion();
91 Assert.assertNotEquals(majorVersion, 0);
92 logger.info("\t getMajorVersion: {}", majorVersion);
93 int minorVersion = driver.getMinorVersion();
94 Assert.assertNotEquals(minorVersion, 0);
95 logger.info("\t getMinorVersion: {}", majorVersion);
96 } catch (Exception e) {
97 logger.error("Cannot create Driver instance: {}", e.getMessage());
98 }
99
100 // Print PostgreSQL server versions
101 Assert.assertNotNull(connection);
102 Statement statement = connection.createStatement();
103 if (statement == null) {
104 logger.info("No online version available.");
105 } else {
106 logger.info("*** PostgreSQL Server ***");
107 String versionString = getVersionString("version");
108 logger.debug("\t version: {}", versionString);
109
110 // Print PostGIS versions
111 logger.info("*** PostGIS Server ***");
112 for (String GISVERSION : POSTGIS_FUNCTIONS) {
113 versionString = getVersionString(GISVERSION);
114 logger.debug("\t {} version: {}", GISVERSION, versionString);
115 }
116 }
117 }
118
119
120 public String getVersionString(String function) throws SQLException {
121 String result = "-- unavailable -- ";
122 try {
123 ResultSet resultSet = statement.executeQuery("SELECT " + function + "()");
124 if (resultSet.next()) {
125 String version = resultSet.getString(1);
126 if (version != null) {
127 result = version.trim();
128 } else {
129 result = "-- null result --";
130 }
131 } else {
132 result = "-- no result --";
133 }
134 } catch (SQLException sqle) {
135 // If the function does not exist, a SQLException will be thrown, but it should be caught an swallowed if
136 // the "does not exist" string is in the error message. The SQLException might be thrown for some other
137 // problem not related to the missing function, so rethrow it if it doesn't contain the string.
138 if (!sqle.getMessage().contains("does not exist")) {
139 throw sqle;
140 }
141 }
142 return result;
143 }
144
145
146 @BeforeClass
147 public void initJdbcConnection(ITestContext ctx) throws Exception {
148 final String jdbcUrlSuffix = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_JDBC_URL_SUFFIX);
149 Assert.assertNotNull(jdbcUrlSuffix);
150 final String jdbcUrl = "jdbc:postgresql" + jdbcUrlSuffix;
151 final String jdbcUsername = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_USER_PARAM_NAME);
152 Assert.assertNotNull(jdbcUsername);
153 final String jdbcPassword = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_PW_PARAM_NAME);
154 Assert.assertNotNull(jdbcPassword);
155 Class.forName(JDBC_DRIVER_CLASS_NAME);
156 connection = DriverManager.getConnection(jdbcUrl, jdbcUsername, jdbcPassword);
157 statement = connection.createStatement();
158 }
159
160
161 @AfterClass
162 public void unallocateDatabaseResources() throws Exception {
163 if ((statement != null) && (!statement.isClosed())) {
164 statement.close();
165 }
166 if ((connection != null) && (!connection.isClosed())) {
167 connection.close();
168 }
169 }
170
171
172 }
+0
-352
jdbc/src/test/java/org/postgis/util/VersionUtilIT.java less more
0 /*
1 * This library is free software; you can redistribute it and/or
2 * modify it under the terms of the GNU Lesser General Public
3 * License as published by the Free Software Foundation; either
4 * version 2.1 of the License, or (at your option) any later version.
5 *
6 * This library is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 * Lesser General Public License for more details.
10 *
11 * You should have received a copy of the GNU Lesser General Public
12 * License along with this library; if not, write to the Free Software
13 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
14 *
15 * (C) 2018 Phillip Ross, phillip.w.g.ross@gmail.com
16 */
17
18 package org.postgis.util;
19
20
21 import net.postgis.tools.testutils.TestContainerController;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
24 import org.testng.Assert;
25 import org.testng.ITestContext;
26 import org.testng.annotations.AfterMethod;
27 import org.testng.annotations.BeforeMethod;
28 import org.testng.annotations.Test;
29
30 import java.sql.Connection;
31 import java.sql.DriverManager;
32 import java.sql.SQLException;
33 import java.util.StringTokenizer;
34
35
36 /**
37 * Integration tests for VersionUtil.
38 *
39 * @author Phillip Ross
40 */
41 public class VersionUtilIT {
42
43 /** The static logger instance. */
44 private static final Logger logger = LoggerFactory.getLogger(VersionUtilIT.class);
45
46 /** The jdbc url prefix containing the jdbc protocol to be used for tests. */
47 private static final String JDBC_URL_PROTOCOL_PREFIX = "jdbc:postgresql";
48
49 /** The JDBC Connection to be used for tests. */
50 private Connection connection = null;
51
52
53 /**
54 * Initializes a new JDBC Connection.
55 *
56 * @param ctx the test context
57 * @throws Exception when an exception occurs
58 */
59 @BeforeMethod
60 public void initJdbcConnection(ITestContext ctx) throws Exception {
61 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
62 final String jdbcUrlSuffix = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_JDBC_URL_SUFFIX);
63 Assert.assertNotNull(jdbcUrlSuffix);
64 final String jdbcUrl = JDBC_URL_PROTOCOL_PREFIX + jdbcUrlSuffix;
65 final String jdbcUsername = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_USER_PARAM_NAME);
66 Assert.assertNotNull(jdbcUsername);
67 final String jdbcPassword = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_PW_PARAM_NAME);
68 Assert.assertNotNull(jdbcPassword);
69 connection = DriverManager.getConnection(jdbcUrl, jdbcUsername, jdbcPassword);
70 }
71
72
73 /**
74 * Un-allocates the JDBC connection.
75 *
76 * @throws Exception when an exception occurs
77 */
78 @AfterMethod
79 public void unallocateDatabaseResources() throws Exception {
80 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
81 if ((connection != null) && (!connection.isClosed())) {
82 connection.close();
83 }
84 }
85
86
87 /**
88 * Test getting version string with a null connection.
89 *
90 * @throws Exception when an exception occurs
91 */
92 @Test(expectedExceptions = NullPointerException.class, expectedExceptionsMessageRegExp = ".*null connection.*")
93 public void test_VersionUtil_GetVersionString_NullConnection() throws Exception {
94 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
95 VersionUtil.getVersionString(null, VersionFunctions.POSTGIS_FULL_VERSION.toString());
96 }
97
98
99 /**
100 * Test getting version string with an invalid connection.
101 *
102 * @throws Exception when an exception occurs
103 */
104 @Test(expectedExceptions = SQLException.class, expectedExceptionsMessageRegExp = ".*connection.*not valid.*")
105 public void test_VersionUtil_GetVersionString_InvalidConnection() throws Exception {
106 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
107 connection.close();
108 VersionUtil.getVersionString(connection, VersionFunctions.POSTGIS_FULL_VERSION.toString());
109 }
110
111
112 /**
113 * Test getting version string with an invalid function name.
114 *
115 * @throws Exception when an exception occurs
116 */
117 @Test(
118 expectedExceptions = SQLException.class,
119 expectedExceptionsMessageRegExp = ".*(?!" + VersionUtil.NONEXISTENT_FUNCTION_ERROR_MESSAGE_CONTENT + ")"
120 )
121 public void test_VersionUtil_GetVersionString_InvalidFunctionName() throws Exception {
122 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
123 VersionUtil.getVersionString(connection, "invalid.function.name");
124 }
125
126
127 /**
128 * Test getting version string with a null function.
129 *
130 * @throws Exception when an exception occurs
131 */
132 @Test(expectedExceptions = NullPointerException.class, expectedExceptionsMessageRegExp = ".*null function.*")
133 public void test_VersionUtil_GetVersionString_NullFunction() throws Exception {
134 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
135 VersionUtil.getVersionString(connection, null);
136 }
137
138
139 /**
140 * Test getting version string of an unavailable function.
141 *
142 * @throws Exception when an exception occurs
143 */
144 @Test
145 public void test_VersionUtil_GetVersionString_Unavailable() throws Exception {
146 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
147 Assert.assertTrue(
148 VersionUtil.getVersionString(connection, "nonexistent")
149 .contains("unavailable")
150 );
151 }
152
153
154 /**
155 * Test getting version strings for all enumerated version functions.
156 *
157 * @throws Exception when an exception occurs
158 */
159 @Test
160 public void test_VersionUtil_GetVersionString_VersionFunctionsEnum() throws Exception {
161 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
162 for (int i = 0; i < VersionFunctions.values().length; i++) {
163 String function = VersionFunctions.values()[i].toString();
164 String version = VersionUtil.getVersionString(connection, function);
165 logger.debug("function [{}] => version string [{}]", function, version);
166 }
167 }
168
169
170 /**
171 * Test getting the server version string with a null connection.
172 *
173 * @throws Exception when an exception occurs
174 */
175 @Test(expectedExceptions = NullPointerException.class, expectedExceptionsMessageRegExp = ".*null connection.*")
176 public void test_VersionUtil_RetrievePostGISServerVersionString_NullConnection() throws Exception {
177 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
178 VersionUtil.retrievePostGISServerVersionString(null);
179 }
180
181
182 /**
183 * Test getting the server version string with an invalid connection.
184 *
185 * @throws Exception when an exception occurs
186 */
187 @Test(expectedExceptions = SQLException.class, expectedExceptionsMessageRegExp = ".*connection.*not valid.*")
188 public void test_VersionUtil_RetrievePostGISServerVersionString_InvalidConnection() throws Exception {
189 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
190 connection.close();
191 VersionUtil.retrievePostGISServerVersionString(connection);
192 }
193
194
195 /**
196 * Test getting the server version string.
197 *
198 * @throws Exception when an exception occurs
199 */
200 @Test
201 public void test_VersionUtil_RetrievePostGISServerVersionString() throws Exception {
202 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
203 String postGISServerVersionString = VersionUtil.retrievePostGISServerVersionString(connection);
204 Assert.assertNotNull(postGISServerVersionString);
205 logger.debug("PostGIS server version string [{}]", postGISServerVersionString);
206 }
207
208
209 /**
210 * Test getting the server version with a null connection.
211 *
212 * @throws Exception when an exception occurs
213 */
214 @Test(expectedExceptions = NullPointerException.class, expectedExceptionsMessageRegExp = ".*null connection.*")
215 public void test_VersionUtil_RetrievePostGISServerVersion_NullConnection() throws Exception {
216 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
217 VersionUtil.retrievePostGISServerVersion(null);
218 }
219
220
221 /**
222 * Test getting the server version with an invalid connection.
223 *
224 * @throws Exception when an exception occurs
225 */
226 @Test(expectedExceptions = SQLException.class, expectedExceptionsMessageRegExp = ".*connection.*not valid.*")
227 public void test_VersionUtil_RetrievePostGISServerVersion_InvalidConnection() throws Exception {
228 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
229 connection.close();
230 VersionUtil.retrievePostGISServerVersion(connection);
231 }
232
233
234 /**
235 * Test getting the server version.
236 *
237 * @throws Exception when an exception occurs
238 */
239 @Test
240 public void test_VersionUtil_RetrievePostGISServerVersion() throws Exception {
241 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
242 final String version = VersionUtil.retrievePostGISServerVersion(connection);
243 Assert.assertNotNull(version);
244 logger.debug("PostGIS server version [{}]", version);
245 }
246
247
248 /**
249 * Test getting the server major version with a null connection.
250 *
251 * @throws Exception when an exception occurs
252 */
253 @Test(expectedExceptions = NullPointerException.class, expectedExceptionsMessageRegExp = ".*null connection.*")
254 public void test_VersionUtil_RetrievePostGISServerMajorVersion_NullConnection() throws Exception {
255 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
256 VersionUtil.retrievePostGISServerMajorVersion(null);
257 }
258
259
260 /**
261 * Test getting the server major version with an invalid connection.
262 *
263 * @throws Exception when an exception occurs
264 */
265 @Test(expectedExceptions = SQLException.class, expectedExceptionsMessageRegExp = ".*connection.*not valid.*")
266 public void test_VersionUtil_RetrievePostGISServerMajorVersion_InvalidConnection() throws Exception {
267 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
268 connection.close();
269 VersionUtil.retrievePostGISServerMajorVersion(connection);
270 }
271
272
273 /**
274 * Test getting the server major version.
275 *
276 * @throws Exception when an exception occurs
277 */
278 @Test
279 public void test_VersionUtil_RetrievePostGISServerMajorVersion() throws Exception {
280 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
281 final String version = VersionUtil.retrievePostGISServerMajorVersion(connection);
282 Assert.assertNotNull(version);
283 logger.debug("PostGIS server major version [{}]", version);
284 }
285
286
287 /**
288 * Test getting the server minor version with a null connection.
289 *
290 * @throws Exception when an exception occurs
291 */
292 @Test(expectedExceptions = NullPointerException.class, expectedExceptionsMessageRegExp = ".*null connection.*")
293 public void test_VersionUtil_RetrievePostGISServerMinorVersion_NullConnection() throws Exception {
294 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
295 VersionUtil.retrievePostGISServerMinorVersion(null);
296 }
297
298
299 /**
300 * Test getting the server minor version with an invalid connection.
301 *
302 * @throws Exception when an exception occurs
303 */
304 @Test(expectedExceptions = SQLException.class, expectedExceptionsMessageRegExp = ".*connection.*not valid.*")
305 public void test_VersionUtil_RetrievePostGISServerMinorVersion_InvalidConnection() throws Exception {
306 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
307 connection.close();
308 VersionUtil.retrievePostGISServerMinorVersion(connection);
309 }
310
311
312 /**
313 * Test getting the server minor version.
314 *
315 * @throws Exception when an exception occurs
316 */
317 @Test
318 public void test_VersionUtil_RetrievePostGISServerMinorVersion() throws Exception {
319 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
320 final String version = VersionUtil.retrievePostGISServerMinorVersion(connection);
321 Assert.assertNotNull(version);
322 logger.debug("PostGIS server minor version [{}]", version);
323 }
324
325
326 /**
327 * Test additional parsing assertions against retrieved versions.
328 *
329 * @throws Exception when an exception occurs
330 */
331 @Test
332 public void testServerVersionParsing() throws Exception {
333 logger.trace("[{}.{}]", getClass(), new Object(){}.getClass().getEnclosingMethod().getName());
334 final String versionString = VersionUtil.retrievePostGISServerVersionString(connection);
335 Assert.assertNotNull(versionString);
336 final String versionFull = VersionUtil.retrievePostGISServerVersion(connection);
337 Assert.assertNotNull(versionFull);
338 Assert.assertTrue(versionString.startsWith(versionFull));
339 final StringTokenizer stringTokenizer =
340 new StringTokenizer(versionString, VersionUtil.POSTGIS_SERVER_VERSION_SEPERATOR);
341 Assert.assertTrue(stringTokenizer.countTokens() > 0);
342 final String versionMajor = VersionUtil.retrievePostGISServerMajorVersion(connection);
343 Assert.assertEquals(versionMajor, stringTokenizer.nextToken());
344 if (stringTokenizer.countTokens() > 1) {
345 final String versionMinor = VersionUtil.retrievePostGISServerMinorVersion(connection);
346 Assert.assertEquals(versionMinor, stringTokenizer.nextToken());
347 }
348 }
349
350
351 }
+0
-19
jdbc/src/test/resources/logback-test.xml less more
0 <configuration debug="false">
1
2 <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
3 <layout class="ch.qos.logback.classic.PatternLayout">
4 <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
5 </layout>
6 </appender>
7
8 <root level="debug">
9 <appender-ref ref="STDOUT" />
10 </root>
11
12 <logger name="com.github.dockerjava" level="ERROR"/>
13 <logger name="org.testcontainers" level="ERROR"/>
14 <logger name="net.postgis" level="ERROR"/>
15
16 <logger name="org.postgis" level="ERROR"/>
17
18 </configuration>
+0
-11
jdbc/src/test/resources/testng.xml less more
0 <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
1 <suite name="Postgis JDBC Extensions Test Suite" verbose="1">
2
3 <test name="Postgis JDBC Tests">
4 <classes>
5 <class name="org.postgis.DatatypesTest"/>
6 <class name="org.postgis.SerializationTest"/>
7 </classes>
8 </test>
9
10 </suite>
+0
-24
jdbc/src/test/resources-filtered/testng-it.xml less more
0 <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
1 <suite name="Postgis JDBC Extensions Integration Test Suite" verbose="1">
2
3 <parameter name="test.container.image-name" value="${test.container.image}"/>
4 <parameter name="test.container.port" value="${test.db.port}"/>
5 <parameter name="test.container.env.user" value="${test.db.username}"/>
6 <parameter name="test.container.env.password" value="${test.db.password}"/>
7 <parameter name="test.container.env.db" value="${test.db.name}"/>
8
9 <test name="Postgis JDBC Integration Tests">
10 <classes>
11 <class name="net.postgis.tools.testutils.TestContainerController"/>
12 <class name="org.postgis.util.VersionUtilIT"/>
13 <class name="org.postgis.DatatypesAutoRegistrationTest"/>
14 <class name="org.postgis.BoxesTest"/>
15 <class name="org.postgis.EmptyGeometriesTest"/>
16 <class name="org.postgis.GeographyDatatypeTest"/>
17 <class name="org.postgis.ParserTest"/>
18 <class name="org.postgis.ServerTest"/>
19 <class name="org.postgis.VersionPrinter"/>
20 </classes>
21 </test>
22
23 </suite>
+0
-27
jdbc/todo.txt less more
0 Todo for PostGIS 1.0 compatible JDBC classes
1
2 - even more Testing, especialy against different postgis,
3 pgjdbc and postgresql releases.
4
5 - Use JUnit for testing (maven)
6
7 - Unify the build of app java projects -> maven
8
9 - Handling of length() - esp. with modifying the geometries
10
11 - Handling of hashCode() - esp. with modifying the geometries
12
13 - Test correctness of toString() and getValue() for compatibility reasons
14
15 - See where the code can be cleaned and leaned.
16
17 - Finish JTS support
18
19 - Creating a sane extension interface for pgjdbc that allows binary
20 transfers and convince upstream to use it, then create support for it.
21
22 - Possibly adding server side code to support plJava
23 http://gborg.postgresql.org/project/pljava/projdisplay.php
24
25 - Rework the BinaryParser/BinaryWriter to work on SQLInput/SQLOutput
26 instances, as well as reworking ValueGetter/ValueSetter to implment those interfaces.
+0
-86
jdbc_jtsparser/pom.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
2 <modelVersion>4.0.0</modelVersion>
3
4 <parent>
5 <groupId>net.postgis</groupId>
6 <artifactId>postgis-java-aggregator</artifactId>
7 <version>2.5.0</version>
8 </parent>
9
10 <artifactId>postgis-jdbc-jtsparser</artifactId>
11 <version>2.5.0</version>
12 <packaging>jar</packaging>
13
14 <name>Postgis JDBC Driver JTS Parser</name>
15 <description>Parser between JTS and PostGIS geometry formats.</description>
16
17 <properties />
18
19 <dependencies>
20 <dependency>
21 <groupId>net.postgis</groupId>
22 <artifactId>postgis-jdbc</artifactId>
23 <version>2.5.0</version>
24 </dependency>
25 <dependency>
26 <groupId>org.locationtech.jts</groupId>
27 <artifactId>jts-core</artifactId>
28 <version>${dependency.jts-version.version}</version>
29 </dependency>
30 <dependency>
31 <groupId>org.locationtech.spatial4j</groupId>
32 <artifactId>spatial4j</artifactId>
33 <version>${dependency.spatial4j.version}</version>
34 </dependency>
35 <dependency>
36 <groupId>net.postgis.tools</groupId>
37 <artifactId>test-utils</artifactId>
38 <version>2.5.0</version>
39 <scope>test</scope>
40 </dependency>
41 </dependencies>
42
43 <build>
44 <testResources>
45 <testResource>
46 <directory>src/test/resources</directory>
47 </testResource>
48 <testResource>
49 <directory>src/test/resources-filtered</directory>
50 <filtering>true</filtering>
51 </testResource>
52 </testResources>
53 <plugins>
54 <plugin>
55 <groupId>org.apache.maven.plugins</groupId>
56 <artifactId>maven-failsafe-plugin</artifactId>
57 <executions>
58 <execution>
59 <id>integration-tests</id>
60 <goals>
61 <goal>integration-test</goal>
62 <goal>verify</goal>
63 </goals>
64 <configuration>
65 <skip>${maven.integration.test.skip}</skip>
66 <forkCount>${failsafe.forkCount}</forkCount>
67 <useSystemClassLoader>${failsafe.useSystemClassLoader}</useSystemClassLoader>
68 <suiteXmlFiles>
69 <suiteXmlFile>${project.build.testOutputDirectory}/testng-it.xml</suiteXmlFile>
70 </suiteXmlFiles>
71 </configuration>
72 </execution>
73 </executions>
74 </plugin>
75 <plugin>
76 <groupId>org.apache.maven.plugins</groupId>
77 <artifactId>maven-surefire-plugin</artifactId>
78 <configuration>
79 <skip>true</skip>
80 </configuration>
81 </plugin>
82 </plugins>
83 </build>
84
85 </project>
+0
-299
jdbc_jtsparser/src/main/java/org/postgis/jts/JTSShape.java less more
0 /*
1 * JTSShape.java
2 *
3 * Binary Parser for JTS - relies on org.postgis V1.0.0+ package.
4 *
5 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
6 *
7 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24
25 package org.postgis.jts;
26
27 import org.locationtech.jts.geom.*;
28 import org.locationtech.jts.geom.Point;
29 import org.locationtech.jts.geom.Polygon;
30 import org.locationtech.jts.geom.impl.PackedCoordinateSequence;
31
32 import java.awt.*;
33 import java.awt.geom.AffineTransform;
34 import java.awt.geom.PathIterator;
35 import java.awt.geom.Point2D;
36 import java.awt.geom.Rectangle2D;
37
38 public class JTSShape implements Shape {
39 static GeometryFactory fac = new GeometryFactory();
40
41 Geometry geom;
42
43 final static LinearRing[] NOSHELLS = {};
44
45 public JTSShape(Geometry _geom) {
46 this.geom = _geom;
47 }
48
49 public JTSShape(JtsGeometry _geom) {
50 this(_geom.getGeometry());
51 }
52
53 public boolean contains(Point2D p) {
54 return contains(p.getX(), p.getY());
55 }
56
57 public boolean contains(double x, double y) {
58 Coordinate c = new Coordinate(x, y);
59 Point p = fac.createPoint(c);
60 return geom.contains(p);
61 }
62
63 public boolean contains(Rectangle2D r) {
64 return contains(r.getMinX(), r.getMinY(), r.getWidth(), r.getHeight());
65 }
66
67 public boolean contains(double x, double y, double w, double h) {
68 Polygon p = createRect(x, y, w, h);
69 return geom.contains(p);
70 }
71
72 protected Polygon createRect(double x, double y, double w, double h) {
73 Coordinate[] coords = { new Coordinate(x, y), new Coordinate(x + w, y), new Coordinate(x + w, y + h) ,new Coordinate(x, y + h) ,new Coordinate(x, y) };
74 PackedCoordinateSequence shell = new PackedCoordinateSequence.Double(coords, 2);
75 Polygon p = fac.createPolygon(fac.createLinearRing(shell), NOSHELLS);
76 return p;
77 }
78
79 public Rectangle2D getBounds2D() {
80 Envelope env = geom.getEnvelopeInternal();
81 return new Rectangle2D.Double(env.getMinX(), env.getMaxX(), env.getWidth(), env.getHeight());
82 }
83
84 public Rectangle getBounds() {
85 // We deal simple code for efficiency here, the getBounds() rounding
86 // rules are ugly...
87 return getBounds2D().getBounds();
88 }
89
90 public PathIterator getPathIterator(AffineTransform at) {
91 return getPathIterator(geom, at);
92 }
93
94 public PathIterator getPathIterator(AffineTransform at, double flatness) {
95 // we don't have much work here, as we only have linear segments, no
96 // "flattening" necessary.
97 return getPathIterator(at);
98 }
99
100 public boolean intersects(Rectangle2D r) {
101 return intersects(r.getMinX(), r.getMinY(), r.getWidth(), r.getHeight());
102 }
103
104 public boolean intersects(double x, double y, double w, double h) {
105 Polygon p = createRect(x, y, w, h);
106 return geom.intersects(p);
107 }
108
109 public static GeometryPathIterator getPathIterator(Geometry geometry, AffineTransform _at) {
110 if (geometry instanceof Point) {
111 return new PointPathIterator((Point) geometry, _at);
112 } else if (geometry instanceof LineString) {
113 return new LineStringPathIterator((LineString) geometry, _at);
114 } else if (geometry instanceof Polygon) {
115 return new PolygonPathIterator((Polygon) geometry, _at);
116 } else {
117 return new GeometryCollectionPathIterator((GeometryCollection) geometry, _at);
118 }
119 }
120
121 public static abstract class GeometryPathIterator implements PathIterator {
122
123 protected final AffineTransform at;
124 protected int index=0;
125
126 GeometryPathIterator(AffineTransform _at) {
127 this.at = _at;
128 }
129
130 public final int getWindingRule() {
131 return PathIterator.WIND_EVEN_ODD;
132 }
133
134 public void next() {
135 index++;
136 }
137 }
138
139 public static class PointPathIterator extends GeometryPathIterator {
140 final Point p;
141
142 public PointPathIterator(Point _p, AffineTransform _at) {
143 super(_at);
144 p = _p;
145 }
146
147 public int currentSegment(float[] coords) {
148 switch (index) {
149 case 0:
150 coords[0] = (float) p.getX();
151 coords[1] = (float) p.getY();
152 at.transform(coords, 0, coords, 0, 1);
153 return PathIterator.SEG_MOVETO;
154 case 1:
155 return PathIterator.SEG_CLOSE;
156 default:
157 throw new IllegalStateException();
158 }
159 }
160
161 public int currentSegment(double[] coords) {
162 switch (index) {
163 case 0:
164 coords[0] = p.getX();
165 coords[1] = p.getY();
166 at.transform(coords, 0, coords, 0, 1);
167 return PathIterator.SEG_MOVETO;
168 case 1:
169 return PathIterator.SEG_CLOSE;
170 default:
171 throw new IllegalStateException();
172 }
173 }
174
175 public boolean isDone() {
176 return index > 1;
177 }
178 }
179
180 public static class LineStringPathIterator extends GeometryPathIterator {
181 CoordinateSequence cs;
182
183 final boolean isRing;
184
185 public LineStringPathIterator(LineString ls, AffineTransform _at) {
186 super(_at);
187 cs = ls.getCoordinateSequence();
188 isRing = ls instanceof LinearRing;
189 }
190
191 /**
192 * only to be called from PolygonPathIterator subclass
193 * @param _cs A coordinate sequence to be used.
194 */
195 protected void reInit(CoordinateSequence _cs) {
196 cs = _cs;
197 index=0;
198 }
199
200 public int currentSegment(float[] coords) {
201 if (index == 0) {
202 coords[0] = (float) cs.getOrdinate(index, 0);
203 coords[1] = (float) cs.getOrdinate(index, 1);
204 at.transform(coords, 0, coords, 0, 1);
205 return PathIterator.SEG_MOVETO;
206 } else if (index < cs.size()) {
207 coords[0] = (float) cs.getOrdinate(index, 0);
208 coords[1] = (float) cs.getOrdinate(index, 1);
209 at.transform(coords, 0, coords, 0, 1);
210 return PathIterator.SEG_LINETO;
211 } else if (isRing && index == cs.size()) {
212 return PathIterator.SEG_CLOSE;
213 } else {
214 throw new IllegalStateException();
215 }
216 }
217
218 public int currentSegment(double[] coords) {
219 if (index == 0) {
220 coords[0] = cs.getOrdinate(index, 0);
221 coords[1] = cs.getOrdinate(index, 1);
222 at.transform(coords, 0, coords, 0, 1);
223 return PathIterator.SEG_MOVETO;
224 } else if (index < cs.size()) {
225 coords[0] = cs.getOrdinate(index, 0);
226 coords[1] = cs.getOrdinate(index, 1);
227 at.transform(coords, 0, coords, 0, 1);
228 return PathIterator.SEG_LINETO;
229 } else if (isRing && index == cs.size()) {
230 return PathIterator.SEG_CLOSE;
231 } else {
232 throw new IllegalStateException();
233 }
234 }
235
236 public boolean isDone() {
237 return isRing ? index > cs.size() : index >= cs.size();
238 }
239 }
240
241 public static class PolygonPathIterator extends LineStringPathIterator {
242 final Polygon pg;
243 int outerindex=-1;
244
245 public PolygonPathIterator(Polygon _pg, AffineTransform _at) {
246 super(_pg.getExteriorRing() ,_at);
247 pg=_pg;
248 index = -1;
249 }
250
251 public boolean isDone() {
252 return outerindex >= pg.getNumInteriorRing();
253 }
254
255 public void next() {
256 super.next();
257 if (super.isDone()) {
258 outerindex++;
259 if (outerindex < pg.getNumInteriorRing()) {
260 super.reInit(pg.getInteriorRingN(outerindex).getCoordinateSequence());
261 }
262 }
263 }
264 }
265
266 public static class GeometryCollectionPathIterator extends GeometryPathIterator {
267 final GeometryCollection coll;
268 GeometryPathIterator current;
269
270 public GeometryCollectionPathIterator(GeometryCollection _coll, AffineTransform _at) {
271 super(_at);
272 coll = _coll;
273 current = getPathIterator(coll.getGeometryN(index), _at);
274 }
275
276 public boolean isDone() {
277 return index > coll.getNumGeometries();
278 }
279
280 public void next() {
281 current.next();
282 if (current.isDone()) {
283 index++;
284 if (index < coll.getNumGeometries()) {
285 current = getPathIterator(coll.getGeometryN(index), at);
286 }
287 }
288 }
289
290 public int currentSegment(float[] coords) {
291 return current.currentSegment(coords);
292 }
293
294 public int currentSegment(double[] coords) {
295 return current.currentSegment(coords);
296 }
297 }
298 }
+0
-262
jdbc_jtsparser/src/main/java/org/postgis/jts/JtsBinaryParser.java less more
0 /*
1 * JtsBinaryParser.java
2 *
3 * Binary Parser for JTS - relies on org.postgis V1.0.0+ package.
4 *
5 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
6 *
7 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24 package org.postgis.jts;
25
26 import org.locationtech.jts.geom.*;
27 import org.locationtech.jts.geom.impl.PackedCoordinateSequence;
28 import org.locationtech.spatial4j.context.jts.JtsSpatialContextFactory;
29 import org.postgis.binary.ByteGetter;
30 import org.postgis.binary.ByteGetter.BinaryByteGetter;
31 import org.postgis.binary.ByteGetter.StringByteGetter;
32 import org.postgis.binary.ValueGetter;
33
34 /**
35 * Parse binary representation of geometries. Currently, only text rep (hexed)
36 * implementation is tested.
37 *
38 * It should be easy to add char[] and CharSequence ByteGetter instances,
39 * although the latter one is not compatible with older jdks.
40 *
41 * I did not implement real unsigned 32-bit integers or emulate them with long,
42 * as both java Arrays and Strings currently can have only 2^31-1 elements
43 * (bytes), so we cannot even get or build Geometries with more than approx.
44 * 2^28 coordinates (8 bytes each).
45 *
46 * @author Markus Schaber, markus.schaber@logix-tt.com
47 *
48 */
49 public class JtsBinaryParser {
50
51 private JtsSpatialContextFactory jtsFactory = new JtsSpatialContextFactory();
52
53 /**
54 * Get the appropriate ValueGetter for my endianness
55 *
56 * @param bytes
57 * The appropriate Byte Getter
58 *
59 * @return the ValueGetter
60 */
61 public static ValueGetter valueGetterForEndian(ByteGetter bytes) {
62 if (bytes.get(0) == ValueGetter.XDR.NUMBER) { // XDR
63 return new ValueGetter.XDR(bytes);
64 } else if (bytes.get(0) == ValueGetter.NDR.NUMBER) {
65 return new ValueGetter.NDR(bytes);
66 } else {
67 throw new IllegalArgumentException("Unknown Endian type:" + bytes.get(0));
68 }
69 }
70
71
72 /**
73 * Parse a hex encoded geometry
74 * @param value String containing the hex data to be parsed
75 * @return the resulting parsed geometry
76 */
77 public Geometry parse(String value) {
78 StringByteGetter bytes = new ByteGetter.StringByteGetter(value);
79 return parseGeometry(valueGetterForEndian(bytes));
80 }
81
82
83 /**
84 * Parse a binary encoded geometry.
85 * @param value byte array containing the binary encoded geometru
86 * @return the resulting parsed geometry
87 */
88 public Geometry parse(byte[] value) {
89 BinaryByteGetter bytes = new ByteGetter.BinaryByteGetter(value);
90 return parseGeometry(valueGetterForEndian(bytes));
91 }
92
93
94 /**
95 * Parse a geometry starting at offset.
96 * @param data ValueGetter for the data to be parsed
97 * @return The resulting Geometry
98 */
99 protected Geometry parseGeometry(ValueGetter data) {
100 return parseGeometry(data, 0, false);
101 }
102
103
104 /**
105 * Parse with a known geometry factory
106 * @param data ValueGetter for the data to be parsed
107 * @param srid the SRID to be used for parsing
108 * @param inheritSrid flag to toggle inheriting SRIDs
109 * @return The resulting Geometry
110 */
111 protected Geometry parseGeometry(ValueGetter data, int srid, boolean inheritSrid) {
112 byte endian = data.getByte(); // skip and test endian flag
113 if (endian != data.endian) {
114 throw new IllegalArgumentException("Endian inconsistency!");
115 }
116 int typeword = data.getInt();
117
118 int realtype = typeword & 0x1FFFFFFF; // cut off high flag bits
119
120 boolean haveZ = (typeword & 0x80000000) != 0;
121 boolean haveM = (typeword & 0x40000000) != 0;
122 boolean haveS = (typeword & 0x20000000) != 0;
123
124 if (haveS) {
125 int newsrid = org.postgis.Geometry.parseSRID(data.getInt());
126 if (inheritSrid && newsrid != srid) {
127 throw new IllegalArgumentException("Inconsistent srids in complex geometry: " + srid + ", " + newsrid);
128 } else {
129 srid = newsrid;
130 }
131 } else if (!inheritSrid) {
132 srid = org.postgis.Geometry.UNKNOWN_SRID;
133 }
134
135 Geometry result;
136 switch (realtype) {
137 case org.postgis.Geometry.POINT:
138 result = parsePoint(data, haveZ, haveM);
139 break;
140 case org.postgis.Geometry.LINESTRING:
141 result = parseLineString(data, haveZ, haveM);
142 break;
143 case org.postgis.Geometry.POLYGON:
144 result = parsePolygon(data, haveZ, haveM, srid);
145 break;
146 case org.postgis.Geometry.MULTIPOINT:
147 result = parseMultiPoint(data, srid);
148 break;
149 case org.postgis.Geometry.MULTILINESTRING:
150 result = parseMultiLineString(data, srid);
151 break;
152 case org.postgis.Geometry.MULTIPOLYGON:
153 result = parseMultiPolygon(data, srid);
154 break;
155 case org.postgis.Geometry.GEOMETRYCOLLECTION:
156 result = parseCollection(data, srid);
157 break;
158 default:
159 throw new IllegalArgumentException("Unknown Geometry Type!");
160 }
161
162 result.setSRID(srid);
163
164 return result;
165 }
166
167 private Point parsePoint(ValueGetter data, boolean haveZ, boolean haveM) {
168 double X = data.getDouble();
169 double Y = data.getDouble();
170 Point result;
171 if (haveZ) {
172 double Z = data.getDouble();
173 result = jtsFactory.getGeometryFactory().createPoint(new Coordinate(X, Y, Z));
174 } else {
175 result = jtsFactory.getGeometryFactory().createPoint(new Coordinate(X, Y));
176 }
177
178 if (haveM) { // skip M value
179 data.getDouble();
180 }
181
182 return result;
183 }
184
185 /** Parse an Array of "full" Geometries */
186 private void parseGeometryArray(ValueGetter data, Geometry[] container, int srid) {
187 for (int i = 0; i < container.length; i++) {
188 container[i] = parseGeometry(data, srid, true);
189 }
190 }
191
192 /**
193 * Parse an Array of "slim" Points (without endianness and type, part of
194 * LinearRing and Linestring, but not MultiPoint!
195 *
196 * @param haveZ
197 * @param haveM
198 */
199 private CoordinateSequence parseCS(ValueGetter data, boolean haveZ, boolean haveM) {
200 int count = data.getInt();
201 int dims = haveZ ? 3 : 2;
202 CoordinateSequence cs = new PackedCoordinateSequence.Double(count, dims, 0);
203
204 for (int i = 0; i < count; i++) {
205 for (int d = 0; d < dims; d++) {
206 cs.setOrdinate(i, d, data.getDouble());
207 }
208 if (haveM) { // skip M value
209 data.getDouble();
210 }
211 }
212 return cs;
213 }
214
215 private MultiPoint parseMultiPoint(ValueGetter data, int srid) {
216 Point[] points = new Point[data.getInt()];
217 parseGeometryArray(data, points, srid);
218 return jtsFactory.getGeometryFactory().createMultiPoint(points);
219 }
220
221 private LineString parseLineString(ValueGetter data, boolean haveZ, boolean haveM) {
222 return jtsFactory.getGeometryFactory().createLineString(parseCS(data, haveZ, haveM));
223 }
224
225 private LinearRing parseLinearRing(ValueGetter data, boolean haveZ, boolean haveM) {
226 return jtsFactory.getGeometryFactory().createLinearRing(parseCS(data, haveZ, haveM));
227 }
228
229 private Polygon parsePolygon(ValueGetter data, boolean haveZ, boolean haveM, int srid) {
230 int holecount = data.getInt() - 1;
231 LinearRing[] rings = new LinearRing[holecount];
232 LinearRing shell = parseLinearRing(data, haveZ, haveM);
233 shell.setSRID(srid);
234 for (int i = 0; i < holecount; i++) {
235 rings[i] = parseLinearRing(data, haveZ, haveM);
236 rings[i].setSRID(srid);
237 }
238 return jtsFactory.getGeometryFactory().createPolygon(shell, rings);
239 }
240
241 private MultiLineString parseMultiLineString(ValueGetter data, int srid) {
242 int count = data.getInt();
243 LineString[] strings = new LineString[count];
244 parseGeometryArray(data, strings, srid);
245 return jtsFactory.getGeometryFactory().createMultiLineString(strings);
246 }
247
248 private MultiPolygon parseMultiPolygon(ValueGetter data, int srid) {
249 int count = data.getInt();
250 Polygon[] polys = new Polygon[count];
251 parseGeometryArray(data, polys, srid);
252 return jtsFactory.getGeometryFactory().createMultiPolygon(polys);
253 }
254
255 private GeometryCollection parseCollection(ValueGetter data, int srid) {
256 int count = data.getInt();
257 Geometry[] geoms = new Geometry[count];
258 parseGeometryArray(data, geoms, srid);
259 return jtsFactory.getGeometryFactory().createGeometryCollection(geoms);
260 }
261 }
+0
-411
jdbc_jtsparser/src/main/java/org/postgis/jts/JtsBinaryWriter.java less more
0 /*
1 * JtsBinaryWriter.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - Binary Writer
4 *
5 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
6 *
7 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24 package org.postgis.jts;
25
26 import org.locationtech.jts.geom.CoordinateSequence;
27 import org.locationtech.jts.geom.Geometry;
28 import org.locationtech.jts.geom.GeometryCollection;
29 import org.locationtech.jts.geom.LineString;
30 import org.locationtech.jts.geom.MultiLineString;
31 import org.locationtech.jts.geom.MultiPoint;
32 import org.locationtech.jts.geom.MultiPolygon;
33 import org.locationtech.jts.geom.Point;
34 import org.locationtech.jts.geom.Polygon;
35
36 import org.postgis.binary.ByteSetter;
37 import org.postgis.binary.ValueSetter;
38
39 /**
40 * Create binary representation of geometries. Currently, only text rep (hexed)
41 * implementation is tested. Supports only 2 dimensional geometries.
42 *
43 * It should be easy to add char[] and CharSequence ByteGetter instances,
44 * although the latter one is not compatible with older jdks.
45 *
46 * I did not implement real unsigned 32-bit integers or emulate them with long,
47 * as both java Arrays and Strings currently can have only 2^31-1 elements
48 * (bytes), so we cannot even get or build Geometries with more than approx.
49 * 2^28 coordinates (8 bytes each).
50 *
51 * @author markus.schaber@logi-track.com
52 *
53 */
54 public class JtsBinaryWriter {
55
56 /**
57 * Get the appropriate ValueGetter for my endianness
58 *
59 * @param bytes The ByteSetter
60 * @param endian The endian to be used
61 * @return the appropriate ValueSetter for the specified endian
62 */
63 public static ValueSetter valueSetterForEndian(ByteSetter bytes, byte endian) {
64 if (endian == ValueSetter.XDR.NUMBER) { // XDR
65 return new ValueSetter.XDR(bytes);
66 } else if (endian == ValueSetter.NDR.NUMBER) {
67 return new ValueSetter.NDR(bytes);
68 } else {
69 throw new IllegalArgumentException("Unknown Endian type:" + endian);
70 }
71 }
72
73 /**
74 * Write a hex encoded geometry
75 *
76 * Currently, geometries with more than 2 dimensions and measures are not
77 * cleanly supported, but SRID is honored.
78 *
79 * @param geom The geometry to be written
80 * @param REP The endianness representation to use for writing
81 * @return String containing the hex-encoded geometry
82 */
83 public String writeHexed(Geometry geom, byte REP) {
84 int length = estimateBytes(geom);
85 ByteSetter.StringByteSetter bytes = new ByteSetter.StringByteSetter(length);
86 writeGeometry(geom, valueSetterForEndian(bytes, REP));
87 return bytes.result();
88 }
89
90 public String writeHexed(Geometry geom) {
91 return writeHexed(geom, ValueSetter.NDR.NUMBER);
92 }
93
94 /**
95 * Write a binary encoded geometry.
96 *
97 * Currently, geometries with more than 2 dimensions and measures are not
98 * cleanly supported, but SRID is honored.
99 *
100 * @param geom The geometry to be written
101 * @param REP The endianness representation to use for writing
102 * @return byte array containing the encoded geometry
103 */
104 public byte[] writeBinary(Geometry geom, byte REP) {
105 int length = estimateBytes(geom);
106 ByteSetter.BinaryByteSetter bytes = new ByteSetter.BinaryByteSetter(length);
107 writeGeometry(geom, valueSetterForEndian(bytes, REP));
108 return bytes.result();
109 }
110
111 public byte[] writeBinary(Geometry geom) {
112 return writeBinary(geom, ValueSetter.NDR.NUMBER);
113 }
114
115
116 /**
117 * Parse a geometry starting at offset.
118 * @param geom The Geometry to be written
119 * @param dest The ValueSettr to write to
120 */
121 protected void writeGeometry(Geometry geom, ValueSetter dest) {
122 final int dimension;
123 if (geom == null) {
124 throw new NullPointerException();
125 } else if (geom.isEmpty()) {
126 // don't set any flag bits
127 dimension = 0;
128 } else {
129 dimension = getCoordDim(geom);
130 if (dimension < 2 || dimension > 4) {
131 throw new IllegalArgumentException("Unsupported geometry dimensionality: " + dimension);
132 }
133 }
134 // write endian flag
135 dest.setByte(dest.endian);
136
137 // write typeword
138 final int plaintype = getWKBType(geom);
139 int typeword = plaintype;
140 if (dimension == 3 || dimension == 4) {
141 typeword |= 0x80000000;
142 }
143 if (dimension == 4) {
144 typeword |= 0x40000000;
145 }
146
147 final boolean haveSrid = checkSrid(geom);
148 if (haveSrid) {
149 typeword |= 0x20000000;
150 }
151
152 dest.setInt(typeword);
153
154 if (haveSrid) {
155 dest.setInt(geom.getSRID());
156 }
157
158 switch (plaintype) {
159 case org.postgis.Geometry.POINT:
160 writePoint((Point) geom, dest);
161 break;
162 case org.postgis.Geometry.LINESTRING:
163 writeLineString((LineString) geom, dest);
164 break;
165 case org.postgis.Geometry.POLYGON:
166 writePolygon((Polygon) geom, dest);
167 break;
168 case org.postgis.Geometry.MULTIPOINT:
169 writeMultiPoint((MultiPoint) geom, dest);
170 break;
171 case org.postgis.Geometry.MULTILINESTRING:
172 writeMultiLineString((MultiLineString) geom, dest);
173 break;
174 case org.postgis.Geometry.MULTIPOLYGON:
175 writeMultiPolygon((MultiPolygon) geom, dest);
176 break;
177 case org.postgis.Geometry.GEOMETRYCOLLECTION:
178 writeCollection((GeometryCollection) geom, dest);
179 break;
180 default:
181 throw new IllegalArgumentException("Unknown Geometry Type: " + plaintype);
182 }
183 }
184
185 public static int getWKBType(Geometry geom) {
186 // We always write empty geometries as empty collections - for OpenGIS
187 // conformance
188 if (geom.isEmpty()) {
189 return org.postgis.Geometry.GEOMETRYCOLLECTION;
190 } else if (geom instanceof Point) {
191 return org.postgis.Geometry.POINT;
192 } else if (geom instanceof org.locationtech.jts.geom.LineString) {
193 return org.postgis.Geometry.LINESTRING;
194 } else if (geom instanceof org.locationtech.jts.geom.Polygon) {
195 return org.postgis.Geometry.POLYGON;
196 } else if (geom instanceof MultiPoint) {
197 return org.postgis.Geometry.MULTIPOINT;
198 } else if (geom instanceof MultiLineString) {
199 return org.postgis.Geometry.MULTILINESTRING;
200 } else if (geom instanceof org.locationtech.jts.geom.MultiPolygon) {
201 return org.postgis.Geometry.MULTIPOLYGON;
202 } if (geom instanceof org.locationtech.jts.geom.GeometryCollection) {
203 return org.postgis.Geometry.GEOMETRYCOLLECTION;
204 } else {
205 throw new IllegalArgumentException("Unknown Geometry Type: " + geom.getClass().getName());
206 }
207 }
208
209 /**
210 * Writes a "slim" Point (without endiannes, srid ant type, only the
211 * ordinates and measure. Used by writeGeometry.
212 */
213 private void writePoint(Point geom, ValueSetter dest) {
214 writeCoordinates(geom.getCoordinateSequence(), getCoordDim(geom), dest);
215 }
216
217 /**
218 * Write a CoordinateSequence, part of LinearRing and Linestring, but not
219 * MultiPoint!
220 */
221 private void writeCoordinates(CoordinateSequence seq, int dims, ValueSetter dest) {
222 for (int i = 0; i < seq.size(); i++) {
223 for (int d = 0; d < dims; d++) {
224 dest.setDouble(seq.getOrdinate(i, d));
225 }
226 }
227 }
228
229 private void writeMultiPoint(MultiPoint geom, ValueSetter dest) {
230 dest.setInt(geom.getNumPoints());
231 for (int i = 0; i < geom.getNumPoints(); i++) {
232 writeGeometry(geom.getGeometryN(i), dest);
233 }
234 }
235
236 private void writeLineString(LineString geom, ValueSetter dest) {
237 dest.setInt(geom.getNumPoints());
238 writeCoordinates(geom.getCoordinateSequence(), getCoordDim(geom), dest);
239 }
240
241 private void writePolygon(Polygon geom, ValueSetter dest) {
242 dest.setInt(geom.getNumInteriorRing() + 1);
243 writeLineString(geom.getExteriorRing(), dest);
244 for (int i = 0; i < geom.getNumInteriorRing(); i++) {
245 writeLineString(geom.getInteriorRingN(i), dest);
246 }
247 }
248
249 private void writeMultiLineString(MultiLineString geom, ValueSetter dest) {
250 writeGeometryArray(geom, dest);
251 }
252
253 private void writeMultiPolygon(MultiPolygon geom, ValueSetter dest) {
254 writeGeometryArray(geom, dest);
255 }
256
257 private void writeCollection(GeometryCollection geom, ValueSetter dest) {
258 writeGeometryArray(geom, dest);
259 }
260
261 private void writeGeometryArray(Geometry geom, ValueSetter dest) {
262 dest.setInt(geom.getNumGeometries());
263 for (int i = 0; i < geom.getNumGeometries(); i++) {
264 writeGeometry(geom.getGeometryN(i), dest);
265 }
266 }
267
268
269 /**
270 * Estimate how much bytes a geometry will need in WKB.
271 * @param geom Geometry to estimate
272 * @return number of bytes needed
273 */
274 protected int estimateBytes(Geometry geom) {
275 int result = 0;
276
277 // write endian flag
278 result += 1;
279
280 // write typeword
281 result += 4;
282
283 if (checkSrid(geom)) {
284 result += 4;
285 }
286
287 switch (getWKBType(geom)) {
288 case org.postgis.Geometry.POINT:
289 result += estimatePoint((Point) geom);
290 break;
291 case org.postgis.Geometry.LINESTRING:
292 result += estimateLineString((LineString) geom);
293 break;
294 case org.postgis.Geometry.POLYGON:
295 result += estimatePolygon((Polygon) geom);
296 break;
297 case org.postgis.Geometry.MULTIPOINT:
298 result += estimateMultiPoint((MultiPoint) geom);
299 break;
300 case org.postgis.Geometry.MULTILINESTRING:
301 result += estimateMultiLineString((MultiLineString) geom);
302 break;
303 case org.postgis.Geometry.MULTIPOLYGON:
304 result += estimateMultiPolygon((MultiPolygon) geom);
305 break;
306 case org.postgis.Geometry.GEOMETRYCOLLECTION:
307 result += estimateCollection((GeometryCollection) geom);
308 break;
309 default:
310 throw new IllegalArgumentException("Unknown Geometry Type: " + getWKBType(geom));
311 }
312 return result;
313 }
314
315 private boolean checkSrid(Geometry geom) {
316 final int srid = geom.getSRID();
317 return (srid > 0);
318 }
319
320 private int estimatePoint(Point geom) {
321 return 8 * getCoordDim(geom);
322 }
323
324 /** Write an Array of "full" Geometries */
325 private int estimateGeometryArray(Geometry container) {
326 int result = 0;
327 for (int i = 0; i < container.getNumGeometries(); i++) {
328 result += estimateBytes(container.getGeometryN(i));
329 }
330 return result;
331 }
332
333 /** Estimate an array of "fat" Points */
334 private int estimateMultiPoint(MultiPoint geom) {
335 // int size
336 int result = 4;
337 if (geom.getNumGeometries() > 0) {
338 // We can shortcut here, compared to estimateGeometryArray, as all
339 // subgeoms have the same fixed size
340 result += geom.getNumGeometries() * estimateBytes(geom.getGeometryN(0));
341 }
342 return result;
343 }
344
345 private int estimateLineString(LineString geom) {
346 if (geom == null || geom.getNumGeometries() == 0) {
347 return 0;
348 } else {
349 return 4 + 8 * getCoordSequenceDim(geom.getCoordinateSequence()) * geom.getCoordinateSequence().size();
350 }
351 }
352
353 private int estimatePolygon(Polygon geom) {
354 // int length
355 int result = 4;
356 result += estimateLineString(geom.getExteriorRing());
357 for (int i = 0; i < geom.getNumInteriorRing(); i++) {
358 result += estimateLineString(geom.getInteriorRingN(i));
359 }
360 return result;
361 }
362
363 private int estimateMultiLineString(MultiLineString geom) {
364 // 4-byte count + subgeometries
365 return 4 + estimateGeometryArray(geom);
366 }
367
368 private int estimateMultiPolygon(MultiPolygon geom) {
369 // 4-byte count + subgeometries
370 return 4 + estimateGeometryArray(geom);
371 }
372
373 private int estimateCollection(GeometryCollection geom) {
374 // 4-byte count + subgeometries
375 return 4 + estimateGeometryArray(geom);
376 }
377
378 public static final int getCoordDim(Geometry geom) {
379 if (geom.isEmpty()) {
380 return 0;
381 }
382 if (geom instanceof Point) {
383 return getCoordSequenceDim(((Point) geom).getCoordinateSequence());
384 } else if (geom instanceof LineString) {
385 return getCoordSequenceDim(((LineString) geom).getCoordinateSequence());
386 } else if (geom instanceof Polygon) {
387 return getCoordSequenceDim(((Polygon) geom).getExteriorRing().getCoordinateSequence());
388 } else {
389 return getCoordDim(geom.getGeometryN(0));
390 }
391 }
392
393 public static final int getCoordSequenceDim(CoordinateSequence coords) {
394 if (coords == null || coords.size() == 0)
395 return 0;
396 // JTS has a really strange way to handle dimensions!
397 // Just have a look at PackedCoordinateSequence and
398 // CoordinateArraySequence
399 int dimensions = coords.getDimension();
400 if (dimensions == 3) {
401 // CoordinateArraySequence will always return 3, so we have to
402 // check, if
403 // the third ordinate contains NaN, then the geom is actually
404 // 2-dimensional
405 return Double.isNaN(coords.getOrdinate(0, CoordinateSequence.Z)) ? 2 : 3;
406 } else {
407 return dimensions;
408 }
409 }
410 }
+0
-165
jdbc_jtsparser/src/main/java/org/postgis/jts/JtsGeometry.java less more
0 /*
1 * JtsGeometry.java
2 *
3 * Wrapper for PostgreSQL JDBC driver to allow transparent reading and writing
4 * of JTS geometries
5 *
6 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
7 *
8 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 *
24 */
25
26 package org.postgis.jts;
27
28 import java.sql.SQLException;
29
30 import org.postgresql.util.PGobject;
31
32 import org.locationtech.jts.geom.CoordinateSequenceFactory;
33 import org.locationtech.jts.geom.Geometry;
34 import org.locationtech.jts.geom.GeometryCollection;
35 import org.locationtech.jts.geom.GeometryFactory;
36 import org.locationtech.jts.geom.Polygon;
37 import org.locationtech.jts.geom.PrecisionModel;
38 import org.locationtech.jts.geom.impl.PackedCoordinateSequenceFactory;
39 import org.locationtech.jts.io.WKTReader;
40
41 /**
42 * JTS Geometry SQL wrapper. Supports PostGIS 1.x (lwgeom hexwkb) for writing
43 * and both PostGIS 0.x (EWKT) and 1.x (lwgeom hexwkb) for reading.
44 *
45 * @author Markus Schaber
46 */
47
48 public class JtsGeometry extends PGobject {
49 /* JDK 1.5 Serialization */
50 private static final long serialVersionUID = 0x100;
51
52 Geometry geom;
53
54 final static JtsBinaryParser bp = new JtsBinaryParser();
55
56 final static JtsBinaryWriter bw = new JtsBinaryWriter();
57
58 final static PrecisionModel prec = new PrecisionModel();
59
60 final static CoordinateSequenceFactory csfac = PackedCoordinateSequenceFactory.DOUBLE_FACTORY;
61
62 final static GeometryFactory geofac = new GeometryFactory(prec, 0, csfac);
63
64 static final WKTReader reader = new WKTReader(geofac);
65
66 /** Constructor called by JDBC drivers */
67 public JtsGeometry() {
68 setType("geometry");
69 }
70
71 public JtsGeometry(Geometry geom) {
72 this();
73 this.geom = geom;
74 }
75
76 public JtsGeometry(String value) throws SQLException {
77 this();
78 setValue(value);
79 }
80
81 public void setValue(String value) throws SQLException {
82 geom = geomFromString(value);
83 }
84
85 public static Geometry geomFromString(String value) throws SQLException {
86 try {
87 value = value.trim();
88 if (value.startsWith("00") || value.startsWith("01")) {
89 return bp.parse(value);
90 } else {
91 Geometry result;
92 // no srid := 0 in JTS world
93 int srid = 0;
94 // break up geometry into srid and wkt
95 if (value.startsWith("SRID=")) {
96 String[] temp = value.split(";");
97 value = temp[1].trim();
98 srid = Integer.parseInt(temp[0].substring(5));
99 }
100
101 result = reader.read(value);
102 setSridRecurse(result, srid);
103 return result;
104 }
105 } catch (Exception E) {
106 E.printStackTrace();
107 throw new SQLException("Error parsing SQL data:" + E);
108 }
109 }
110
111
112 /**
113 * Recursively set a srid for the geometry and all subgeometries
114 * @param geom Geometry to work on
115 * @param srid SRID to be set to
116 */
117 public static void setSridRecurse(final Geometry geom, final int srid) {
118 geom.setSRID(srid);
119 if (geom instanceof GeometryCollection) {
120 final int subcnt = geom.getNumGeometries();
121 for (int i = 0; i < subcnt; i++) {
122 setSridRecurse(geom.getGeometryN(i), srid);
123 }
124 } else if (geom instanceof Polygon) {
125 Polygon poly = (Polygon) geom;
126 poly.getExteriorRing().setSRID(srid);
127 final int subcnt = poly.getNumInteriorRing();
128 for (int i = 0; i < subcnt; i++) {
129 poly.getInteriorRingN(i).setSRID(srid);
130 }
131 }
132 }
133
134 public Geometry getGeometry() {
135 return geom;
136 }
137
138 public String toString() {
139 return geom.toString();
140 }
141
142 public String getValue() {
143 return bw.writeHexed(getGeometry());
144 }
145
146 public Object clone() {
147 JtsGeometry obj = new JtsGeometry(geom);
148 obj.setType(type);
149 return obj;
150 }
151
152 public boolean equals(Object obj) {
153 if ((obj != null) && (obj instanceof JtsGeometry)) {
154 Geometry other = ((JtsGeometry) obj).geom;
155 if (this.geom == other) { // handles identity as well as both
156 // ==null
157 return true;
158 } else if (this.geom != null && other != null) {
159 return other.equals(this.geom);
160 }
161 }
162 return false;
163 }
164 }
+0
-160
jdbc_jtsparser/src/main/java/org/postgis/jts/JtsGisWrapper.java less more
0 /*
1 * JtsGisWrapper.java
2 *
3 * Allows transparent usage of JTS Geometry classes via PostgreSQL JDBC driver
4 * connected to a PostGIS enabled PostgreSQL server.
5 *
6 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
7 *
8 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 *
24 */
25
26 package org.postgis.jts;
27
28 import org.postgresql.Driver;
29 import org.postgresql.PGConnection;
30
31 import java.sql.Connection;
32 import java.sql.SQLException;
33 import java.util.Properties;
34
35 /**
36 * JtsGisWrapper
37 *
38 * Wraps the PostGreSQL Driver to add the JTS/PostGIS Object Classes.
39 *
40 * This method currently works with J2EE DataSource implementations, and with
41 * DriverManager framework.
42 *
43 * Simply replace the "jdbc:postgresql:" with a "jdbc:postgresql_JTS" in the
44 * jdbc URL.
45 *
46 * @author markus.schaber@logix-tt.com
47 *
48 */
49 public class JtsGisWrapper extends Driver {
50
51 private static final String POSTGRES_PROTOCOL = "jdbc:postgresql:";
52 private static final String POSTGIS_PROTOCOL = "jdbc:postgresql_JTS:";
53 public static final String REVISION = "$Revision$";
54
55 public JtsGisWrapper() {
56 super();
57 }
58
59 static {
60 try {
61 // Analogy to org.postgresql.Driver
62 java.sql.DriverManager.registerDriver(new JtsGisWrapper());
63 } catch (SQLException e) {
64 e.printStackTrace();
65 }
66 }
67
68 /**
69 * Creates a postgresql connection, and then adds the PostGIS data types to
70 * it calling addpgtypes()
71 *
72 * @param url the URL of the database to connect to
73 * @param info a list of arbitrary tag/value pairs as connection arguments
74 * @return a connection to the URL or null if it isnt us
75 * @exception SQLException if a database access error occurs
76 *
77 * @see java.sql.Driver#connect
78 * @see org.postgresql.Driver
79 */
80 public java.sql.Connection connect(String url, Properties info) throws SQLException {
81 url = mangleURL(url);
82 Connection result = super.connect(url, info);
83 addGISTypes((PGConnection) result);
84 return result;
85 }
86
87 /**
88 * Adds the JTS/PostGIS Data types to a PG Connection.
89 * @param pgconn The PGConnection object to add the types to
90 * @throws SQLException when an SQLException occurs
91 */
92 public static void addGISTypes(PGConnection pgconn) throws SQLException {
93 pgconn.addDataType("geometry", org.postgis.jts.JtsGeometry.class);
94 pgconn.addDataType("box3d", org.postgis.PGbox3d.class);
95 pgconn.addDataType("box2d", org.postgis.PGbox2d.class);
96 }
97
98 /**
99 * Mangles the PostGIS URL to return the original PostGreSQL URL
100 *
101 * @param url String containing the url to be "mangled"
102 * @return "mangled" string
103 * @throws SQLException when a SQLException occurs
104 */
105 public static String mangleURL(String url) throws SQLException {
106 if (url.startsWith(POSTGIS_PROTOCOL)) {
107 return POSTGRES_PROTOCOL + url.substring(POSTGIS_PROTOCOL.length());
108 } else {
109 throw new SQLException("Unknown protocol or subprotocol in url " + url);
110 }
111 }
112
113 /**
114 * Returns true if the driver thinks it can open a connection to the given
115 * URL. Typically, drivers will return true if they understand the
116 * subprotocol specified in the URL and false if they don't. Our protocols
117 * start with jdbc:postgresql_postGIS:
118 *
119 * @see java.sql.Driver#acceptsURL
120 * @param url the URL of the driver
121 * @return true if this driver accepts the given URL
122 */
123 public boolean acceptsURL(String url) {
124 try {
125 url = mangleURL(url);
126 } catch (SQLException e) {
127 return false;
128 }
129 return super.acceptsURL(url);
130 }
131
132 /**
133 * Gets the underlying drivers major version number
134 *
135 * @return the drivers major version number
136 */
137
138 public int getMajorVersion() {
139 return super.getMajorVersion();
140 }
141
142 /**
143 * Get the underlying drivers minor version number
144 *
145 * @return the drivers minor version number
146 */
147 public int getMinorVersion() {
148 return super.getMinorVersion();
149 }
150
151 /**
152 * Returns our own CVS version plus postgres Version
153 *
154 * @return String representation of the version
155 */
156 public static String getVersion() {
157 return "JtsGisWrapper " + REVISION + ", wrapping " + Driver.getVersion();
158 }
159 }
+0
-166
jdbc_jtsparser/src/main/java/org/postgis/jts/JtsWrapper.java less more
0 /*
1 * JtsWrapper.java
2 *
3 * Allows transparent usage of JTS Geometry classes via PostgreSQL JDBC driver
4 * connected to a PostGIS enabled PostgreSQL server.
5 *
6 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
7 *
8 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 *
24 */
25
26 package org.postgis.jts;
27
28 import java.sql.Connection;
29 import java.sql.SQLException;
30 import java.util.Properties;
31 import java.util.logging.Level;
32 import java.util.logging.Logger;
33
34 import org.postgresql.Driver;
35 import org.postgresql.PGConnection;
36
37 /**
38 * JtsWrapper
39 *
40 * Wraps the PostGreSQL Driver to add the JTS/PostGIS Object Classes.
41 *
42 * This method currently works with J2EE DataSource implementations, and with
43 * DriverManager framework.
44 *
45 * Simply replace the "jdbc:postgresql:" with a "jdbc:postgres_jts:" in the jdbc
46 * URL.
47 *
48 * When using the drivermanager, you need to initialize JtsWrapper instead of
49 * (or in addition to) org.postgresql.Driver. When using a J2EE DataSource
50 * implementation, set the driver class property in the datasource config, the
51 * following works for jboss:
52 *
53 * &lt;driver-class&gt;org.postgis.jts.PostGisWrapper&lt;/driver-class&gt;
54 *
55 * @author markus.schaber@logix-tt.com
56 *
57 */
58 public class JtsWrapper extends Driver {
59
60 protected static final Logger logger = Logger.getLogger("org.postgis.DriverWrapper");
61
62 private static final String POSTGRES_PROTOCOL = "jdbc:postgresql:";
63 private static final String POSTGIS_PROTOCOL = "jdbc:postgres_jts:";
64 public static final String REVISION = "$Revision$";
65
66 public JtsWrapper() {
67 super();
68 }
69
70 static {
71 try {
72 // Try to register ourself to the DriverManager
73 java.sql.DriverManager.registerDriver(new JtsWrapper());
74 } catch (SQLException e) {
75 logger.log(Level.WARNING, "Error registering PostgreSQL Jts Wrapper Driver", e);
76 }
77 }
78
79 /**
80 * Creates a postgresql connection, and then adds the JTS GIS data types to
81 * it calling addpgtypes()
82 *
83 * @param url the URL of the database to connect to
84 * @param info a list of arbitrary tag/value pairs as connection arguments
85 * @return a connection to the URL or null if it isnt us
86 * @exception SQLException if a database access error occurs
87 *
88 * @see java.sql.Driver#connect
89 * @see org.postgresql.Driver
90 */
91 public java.sql.Connection connect(String url, Properties info) throws SQLException {
92 url = mangleURL(url);
93 Connection result = super.connect(url, info);
94 addGISTypes((PGConnection)result);
95 return result;
96 }
97
98 /**
99 * Adds the JTS/PostGIS Data types to a PG Connection.
100 * @param pgconn The PGConnection object to add the types to
101 * @throws SQLException when an SQLException occurs
102 */
103 public static void addGISTypes(PGConnection pgconn) throws SQLException {
104 pgconn.addDataType("geometry", org.postgis.jts.JtsGeometry.class);
105 }
106
107 /**
108 * Mangles the PostGIS URL to return the original PostGreSQL URL
109 *
110 * @param url String containing the url to be "mangled"
111 * @return "mangled" string
112 * @throws SQLException when a SQLException occurs
113 */
114 public static String mangleURL(String url) throws SQLException {
115 if (url.startsWith(POSTGIS_PROTOCOL)) {
116 return POSTGRES_PROTOCOL + url.substring(POSTGIS_PROTOCOL.length());
117 } else {
118 throw new SQLException("Unknown protocol or subprotocol in url " + url);
119 }
120 }
121
122 /**
123 * Check whether the driver thinks he can handle the given URL.
124 *
125 * @see java.sql.Driver#acceptsURL
126 * @param url the URL of the driver
127 * @return true if this driver accepts the given URL
128 */
129 public boolean acceptsURL(String url) {
130 try {
131 url = mangleURL(url);
132 } catch (SQLException e) {
133 return false;
134 }
135 return super.acceptsURL(url);
136 }
137
138 /**
139 * Gets the underlying drivers major version number
140 *
141 * @return the drivers major version number
142 */
143
144 public int getMajorVersion() {
145 return super.getMajorVersion();
146 }
147
148 /**
149 * Get the underlying drivers minor version number
150 *
151 * @return the drivers minor version number
152 */
153 public int getMinorVersion() {
154 return super.getMinorVersion();
155 }
156
157 /**
158 * Returns our own CVS version plus postgres Version
159 *
160 * @return String representation of the version
161 */
162 public static String getVersion() {
163 return "JtsGisWrapper " + REVISION + ", wrapping " + Driver.getVersion();
164 }
165 }
+0
-1
jdbc_jtsparser/src/main/javadoc/overview.html less more
0 <body><p>Parser between JTS and PostGIS geometry formats.</p></body>
+0
-446
jdbc_jtsparser/src/test/java/org/postgis/jts/JtsParserTest.java less more
0 /*
1 * JtsParserTest.java
2 *
3 * JtsParserTest for JTS - relies on org.postgis V1.0.0+ package.
4 *
5 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 *
21 */
22
23 package org.postgis.jts;
24
25
26 import org.postgis.binary.ValueSetter;
27
28 import org.locationtech.jts.geom.*;
29 import net.postgis.tools.testutils.TestContainerController;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32 import org.testng.Assert;
33 import org.testng.ITestContext;
34 import org.testng.annotations.AfterClass;
35 import org.testng.annotations.BeforeClass;
36 import org.testng.annotations.Test;
37
38 import java.sql.*;
39
40
41 /**
42 * JtsParseTest
43 *
44 * This test class was adapted from the {@code JtsTestParsr} example standalone class.
45 * It is meant to be run in standalone mode or run against a PostGIS database, but it will need to be
46 * fixed to run against a PostGIS database as it currently fails in some places with an error:
47 * {@literal function asewkb(geometry) does not exist}
48 */
49 public class JtsParserTest {
50
51 private static final Logger logger = LoggerFactory.getLogger(JtsParserTest.class);
52
53 private static final String JTS_WRAPPER_CLASS_NAME = "org.postgis.jts.JtsWrapper";
54
55 /** The srid we use for the srid tests */
56 public static final int SRID = 4326;
57
58 /** The string prefix we get for the srid tests */
59 public static final String SRIDPREFIX = "SRID=" + SRID + ";";
60
61 /**
62 * Our set of geometries to test.
63 */
64 public static final String ALL = "ALL";
65 public static final String ONLY10 = "ONLY10";
66 public static final String EQUAL10 = "EQUAL10";
67 public static final String[][] testset = new String[][] {
68 { ALL, // 2D
69 "POINT(10 10)" },
70 { ALL, // 3D with 3rd coordinate set to 0
71 "POINT(10 10 0)" },
72 { ALL, // 3D
73 "POINT(10 10 20)" },
74 { ALL, "MULTIPOINT(11 12, 20 20)" },
75 { ALL, "MULTIPOINT(11 12 13, 20 20 20)" },
76 { ALL, "LINESTRING(10 10,20 20,50 50,34 34)" },
77 { ALL, "LINESTRING(10 10 20,20 20 20,50 50 50,34 34 34)" },
78 { ALL, "POLYGON((10 10,20 10,20 20,20 10,10 10),(5 5,5 6,6 6,6 5,5 5))" },
79 { ALL, "POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))" },
80 {
81 ALL,
82 "MULTIPOLYGON(((10 10,20 10,20 20,20 10,10 10),(5 5,5 6,6 6,6 5,5 5)),((10 10,20 10,20 20,20 10,10 10),(5 5,5 6,6 6,6 5,5 5)))" },
83 {
84 ALL,
85 "MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))" },
86 { ALL, "MULTILINESTRING((10 10,20 10,20 20,20 10,10 10),(5 5,5 6,6 6,6 5,5 5))" },
87 { ALL, "MULTILINESTRING((10 10 5,20 10 5,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))" },
88 { ALL, "GEOMETRYCOLLECTION(POINT(10 10),POINT(20 20))" },
89 { ALL, "GEOMETRYCOLLECTION(POINT(10 10 20),POINT(20 20 20))" },
90 {
91 ALL,
92 "GEOMETRYCOLLECTION(LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34),LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34))" },
93 {
94 ALL,
95 "GEOMETRYCOLLECTION(POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))" },
96 { ONLY10, // Cannot be parsed by 0.X servers
97 "GEOMETRYCOLLECTION(MULTIPOINT(10 10 10, 20 20 20),MULTIPOINT(10 10 10, 20 20 20))" },
98 { EQUAL10, // PostGIs 0.X "flattens" this geometry, so it is not
99 // equal after reparsing.
100 "GEOMETRYCOLLECTION(MULTILINESTRING((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))" },
101 { EQUAL10,// PostGIs 0.X "flattens" this geometry, so it is not
102 // equal
103 // after reparsing.
104 "GEOMETRYCOLLECTION(MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))),MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))))" },
105 {
106 ALL,
107 "GEOMETRYCOLLECTION(POINT(10 10 20),LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34),POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))" },
108 { ONLY10, // Collections that contain both X and MultiX do not
109 // work on
110 // PostGIS 0.x
111 "GEOMETRYCOLLECTION(POINT(10 10 20),MULTIPOINT(10 10 10, 20 20 20),LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34),POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))),MULTILINESTRING((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))" },
112 { ALL,// new (correct) representation
113 "GEOMETRYCOLLECTION EMPTY" },
114 };
115
116 private static JtsBinaryParser jtsBinaryParser = new JtsBinaryParser();
117
118 private static final JtsBinaryWriter jtsBinaryWriter = new JtsBinaryWriter();
119
120 private Connection connection = null;
121
122 private Statement statement = null;
123
124
125 @Test
126 public void test() throws Exception {
127 for (String[] aTestset : testset) {
128 test(aTestset[1], aTestset[0]);
129 test(SRIDPREFIX + aTestset[1], aTestset[0]);
130 }
131 }
132
133
134 public void test(String WKT, String flags) throws SQLException {
135 logger.debug("Original: {}", WKT);
136 Geometry geom = JtsGeometry.geomFromString(WKT);
137 String parsed = geom.toString();
138 if (WKT.startsWith("SRID=")) {
139 parsed = "SRID=" + geom.getSRID() + ";" + parsed;
140 }
141 logger.debug("Parsed: {}", parsed);
142 Geometry regeom = JtsGeometry.geomFromString(parsed);
143 String reparsed = regeom.toString();
144 if (WKT.startsWith("SRID=")) {
145 reparsed = "SRID=" + geom.getSRID() + ";" + reparsed;
146 }
147 logger.debug("Re-Parsed: {}", reparsed);
148 Assert.assertEquals(geom, regeom, "Geometries are not equal");
149 Assert.assertEquals(geom.getSRID(), regeom.getSRID(), "Geometry SRIDs are not equal");
150 Assert.assertEquals(reparsed, parsed, "Text Reps are not equal");
151
152 String hexNWKT = jtsBinaryWriter.writeHexed(geom, ValueSetter.NDR.NUMBER);
153 logger.debug("NDRHex: {}", hexNWKT);
154 regeom = JtsGeometry.geomFromString(hexNWKT);
155 logger.debug("ReNDRHex: {}", regeom);
156 Assert.assertEquals(geom, regeom, "Geometries are not equal");
157
158 String hexXWKT = jtsBinaryWriter.writeHexed(geom, ValueSetter.XDR.NUMBER);
159 logger.debug("XDRHex: {}", hexXWKT);
160 regeom = JtsGeometry.geomFromString(hexXWKT);
161 logger.debug("ReXDRHex: {}", regeom);
162 Assert.assertEquals(geom, regeom, "Geometries are not equal");
163
164 byte[] NWKT = jtsBinaryWriter.writeBinary(geom, ValueSetter.NDR.NUMBER);
165 regeom = jtsBinaryParser.parse(NWKT);
166 logger.debug("NDR: {}", regeom);
167 Assert.assertEquals(geom, regeom, "Geometries are not equal");
168
169 byte[] XWKT = jtsBinaryWriter.writeBinary(geom, ValueSetter.XDR.NUMBER);
170 regeom = jtsBinaryParser.parse(XWKT);
171 logger.debug("XDR: {}", regeom);
172 Assert.assertEquals(geom, regeom, "Geometries are not equal");
173
174 Geometry coordArrayGeom = rebuildCS(geom);
175 logger.debug("CoordArray: {}", regeom);
176 Assert.assertEquals(geom, coordArrayGeom, "Geometries are not equal");
177
178 String coordArrayWKT = jtsBinaryWriter.writeHexed(coordArrayGeom, ValueSetter.NDR.NUMBER);
179 logger.debug("HexCArray: {}", coordArrayWKT);
180 Assert.assertEquals(coordArrayWKT, hexNWKT, "CoordArray HexWKT is not equal");
181
182 int serverPostgisMajor = getPostgisMajor();
183
184 if ((flags.equals(ONLY10)) && serverPostgisMajor < 1) {
185 logger.info("PostGIS server too old, skipping test on connection {}", connection.getCatalog());
186 } else {
187 logger.debug("Testing on connection {}", connection.getCatalog());
188
189 Geometry sqlGeom = viaSQL(WKT, statement);
190 logger.debug("SQLin: {}", sqlGeom.toString());
191 if (!geom.equalsExact(sqlGeom)) {
192 logger.warn("Geometries after SQL are not equal");
193 if (flags.equals(EQUAL10) && serverPostgisMajor < 1) {
194 logger.info("This is expected with PostGIS {}.X", serverPostgisMajor);
195 } else {
196 Assert.fail();
197 }
198 }
199
200 Geometry sqlreGeom = viaSQL(parsed, statement);
201 logger.debug("SQLout: {}", sqlreGeom);
202 if (!geom.equalsExact(sqlreGeom)) {
203 logger.warn("Reparsed Geometries after SQL are not equal");
204 if (flags.equals(EQUAL10) && serverPostgisMajor < 1) {
205 logger.info("This is expected with PostGIS {}.X", serverPostgisMajor);
206 } else {
207 Assert.fail();
208 }
209 }
210
211 sqlreGeom = viaPrepSQL(geom, connection);
212 logger.debug("Prepared: {}", sqlreGeom);
213 if (!geom.equalsExact(sqlreGeom)) {
214 logger.debug("Reparsed Geometries after prepared StatementSQL are not equal");
215 if (flags.equals(EQUAL10) && serverPostgisMajor < 1) {
216 logger.info("This is expected with PostGIS {}.X", serverPostgisMajor);
217 } else {
218 Assert.fail();
219 }
220 }
221
222 // asEWKT() function is not present on PostGIS 0.X, and the test
223 // is pointless as 0.X uses EWKT as canonical rep so the same
224 // functionality was already tested above.
225 if (serverPostgisMajor >= 1) {
226 sqlGeom = ewktViaSQL(WKT, statement);
227 logger.debug("asEWKT: {}", sqlGeom);
228 Assert.assertEquals(geom, sqlGeom);
229
230 sqlGeom = ewkbViaSQL(WKT, statement);
231 logger.debug("asEWKB: {}", sqlGeom);
232 Assert.assertEquals(geom, sqlGeom);
233
234 sqlGeom = viaSQL(hexNWKT, statement);
235 logger.debug("hexNWKT: {}", sqlGeom);
236 Assert.assertEquals(geom, sqlGeom);
237
238 sqlGeom = viaSQL(hexXWKT, statement);
239 logger.debug("hexXWKT: {}", sqlGeom);
240 Assert.assertEquals(geom, sqlGeom);
241
242 sqlGeom = binaryViaSQL(NWKT, connection);
243 logger.debug("NWKT: {}", sqlGeom);
244 Assert.assertEquals(geom, sqlGeom);
245
246 sqlGeom = binaryViaSQL(XWKT, connection);
247 logger.debug("XWKT: {}", sqlGeom);
248 Assert.assertEquals(geom, sqlGeom);
249 }
250 }
251 }
252
253
254 /** Pass a geometry representation through the SQL server */
255 private static Geometry viaSQL(String rep, Statement stat) throws SQLException {
256 ResultSet rs = stat.executeQuery("SELECT geometry_in('" + rep + "')");
257 rs.next();
258 return ((JtsGeometry) rs.getObject(1)).getGeometry();
259 }
260
261
262 /**
263 * Pass a geometry representation through the SQL server via prepared
264 * statement
265 */
266 private static Geometry viaPrepSQL(Geometry geom, Connection conn) throws SQLException {
267 PreparedStatement prep = conn.prepareStatement("SELECT ?::geometry");
268 JtsGeometry wrapper = new JtsGeometry(geom);
269 prep.setObject(1, wrapper, Types.OTHER);
270 ResultSet rs = prep.executeQuery();
271 rs.next();
272 JtsGeometry resultwrapper = ((JtsGeometry) rs.getObject(1));
273 return resultwrapper.getGeometry();
274 }
275
276
277 /** Pass a geometry representation through the SQL server via EWKT */
278 private static Geometry ewktViaSQL(String rep, Statement stat) throws SQLException {
279 ResultSet rs = stat.executeQuery("SELECT ST_AsEWKT(geometry_in('" + rep + "'))");
280 rs.next();
281 String resrep = rs.getString(1);
282 return JtsGeometry.geomFromString(resrep);
283 }
284
285
286 /** Pass a geometry representation through the SQL server via EWKB */
287 private static Geometry ewkbViaSQL(String rep, Statement stat) throws SQLException {
288 ResultSet rs = stat.executeQuery("SELECT ST_AsEWKB(geometry_in('" + rep + "'))");
289 rs.next();
290 byte[] resrep = rs.getBytes(1);
291 return jtsBinaryParser.parse(resrep);
292 }
293
294
295 /** Pass a EWKB geometry representation through the server */
296 private static Geometry binaryViaSQL(byte[] rep, Connection conn) throws SQLException {
297 PreparedStatement prep = conn.prepareStatement("SELECT ?::bytea::geometry");
298 prep.setBytes(1, rep);
299 ResultSet rs = prep.executeQuery();
300 rs.next();
301 JtsGeometry resultwrapper = ((JtsGeometry) rs.getObject(1));
302 return resultwrapper.getGeometry();
303 }
304
305
306 // Rebuild given Geometry with a CoordinateArraySequence implementation.
307 public static Geometry rebuildCS(Geometry geom) {
308 if (geom instanceof Point) {
309 return rebuildCSPoint((Point)geom);
310 } else if (geom instanceof MultiPoint) {
311 return rebuildCSMP((MultiPoint)geom);
312 } else if (geom instanceof LineString) {
313 return rebuildCSLS((LineString)geom);
314 } else if (geom instanceof MultiLineString) {
315 return rebuildCSMLS((MultiLineString)geom);
316 } else if (geom instanceof Polygon) {
317 return rebuildCSP((Polygon)geom);
318 } else if (geom instanceof MultiPolygon) {
319 return rebuildCSMP((MultiPolygon)geom);
320 } else if (geom instanceof GeometryCollection) {
321 return rebuildCSGC((GeometryCollection)geom);
322 } else {
323 throw new AssertionError();
324 }
325 }
326
327
328 private static Point rebuildCSPoint(Point point) {
329 Point result = point.getFactory().createPoint(point.getCoordinate());
330 result.setSRID(point.getSRID());
331 return result;
332 }
333
334
335 private static MultiPoint rebuildCSMP(MultiPoint mp) {
336 Point[] points = new Point[mp.getNumGeometries()];
337 for (int i=0; i < points.length; i++) {
338 points[i] = rebuildCSPoint((Point) mp.getGeometryN(i));
339 }
340 MultiPoint result = mp.getFactory().createMultiPoint(points);
341 result.setSRID(mp.getSRID());
342 return result;
343 }
344
345
346 private static MultiPolygon rebuildCSMP(MultiPolygon multipoly) {
347 Polygon[] polygons = new Polygon[multipoly.getNumGeometries()];
348 for (int i=0; i < polygons.length; i++) {
349 polygons[i] = rebuildCSP((Polygon)multipoly.getGeometryN(i));
350 }
351 MultiPolygon result = multipoly.getFactory().createMultiPolygon(polygons);
352 result.setSRID(multipoly.getSRID());
353 return result;
354 }
355
356
357 private static LineString rebuildCSLS(LineString line) {
358 LineString result = line.getFactory().createLineString(line.getCoordinates());
359 result.setSRID(line.getSRID());
360 return result;
361 }
362
363
364 private static MultiLineString rebuildCSMLS(MultiLineString multiline) {
365 LineString[] polygons = new LineString[multiline.getNumGeometries()];
366 for (int i=0; i < polygons.length; i++) {
367 polygons[i] = rebuildCSLS((LineString)multiline.getGeometryN(i));
368 }
369 MultiLineString result = multiline.getFactory().createMultiLineString(polygons);
370 result.setSRID(multiline.getSRID());
371 return result;
372
373 }
374
375
376 private static Polygon rebuildCSP(Polygon polygon) {
377 LinearRing outer = rebuildLR(polygon.getExteriorRing());
378 LinearRing[] holes = new LinearRing[polygon.getNumInteriorRing()];
379 for (int i=0; i < holes.length; i++) {
380 holes[i] = rebuildLR(polygon.getInteriorRingN(i));
381 }
382 Polygon result = polygon.getFactory().createPolygon(outer, holes);
383 result.setSRID(polygon.getSRID());
384 return result;
385 }
386
387
388 private static LinearRing rebuildLR(LineString ring) {
389 LinearRing result = ring.getFactory().createLinearRing(ring.getCoordinates());
390 result.setSRID(ring.getSRID());
391 return result;
392 }
393
394
395 private static Geometry rebuildCSGC(GeometryCollection coll) {
396 Geometry[] geoms = new Geometry[coll.getNumGeometries()];
397 for (int i = 0; i < coll.getNumGeometries(); i++) {
398 geoms[i] = rebuildCS(coll.getGeometryN(i));
399 }
400 Geometry result = coll.getFactory().createGeometryCollection(geoms);
401 result.setSRID(coll.getSRID());
402 return result;
403 }
404
405
406 public int getPostgisMajor() throws SQLException {
407 ResultSet resultSet = statement.executeQuery("SELECT postgis_version()");
408 resultSet.next();
409 String version = resultSet.getString(1);
410 if (version == null) {
411 throw new SQLException("postgis_version returned NULL!");
412 }
413 version = version.trim();
414 int idx = version.indexOf('.');
415 return Integer.parseInt(version.substring(0, idx));
416 }
417
418
419 @BeforeClass
420 public void initJdbcConnection(ITestContext ctx) throws Exception {
421 final String jdbcUrlSuffix = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_JDBC_URL_SUFFIX);
422 Assert.assertNotNull(jdbcUrlSuffix);
423 final String jdbcUrl = "jdbc:postgres_jts" + jdbcUrlSuffix;
424 final String jdbcUsername = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_USER_PARAM_NAME);
425 Assert.assertNotNull(jdbcUsername);
426 final String jdbcPassword = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_PW_PARAM_NAME);
427 Assert.assertNotNull(jdbcPassword);
428 Class.forName(JTS_WRAPPER_CLASS_NAME);
429 connection = DriverManager.getConnection(jdbcUrl, jdbcUsername, jdbcPassword);
430 statement = connection.createStatement();
431 }
432
433
434 @AfterClass
435 public void unallocateDatabaseResources() throws Exception {
436 if ((statement != null) && (!statement.isClosed())) {
437 statement.close();
438 }
439 if ((connection != null) && (!connection.isClosed())) {
440 connection.close();
441 }
442 }
443
444
445 }
+0
-19
jdbc_jtsparser/src/test/resources/logback-test.xml less more
0 <configuration debug="false">
1
2 <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
3 <layout class="ch.qos.logback.classic.PatternLayout">
4 <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
5 </layout>
6 </appender>
7
8 <root level="debug">
9 <appender-ref ref="STDOUT" />
10 </root>
11
12 <logger name="com.github.dockerjava" level="ERROR"/>
13 <logger name="org.testcontainers" level="ERROR"/>
14 <logger name="net.postgis" level="ERROR"/>
15
16 <logger name="org.postgis.jts" level="ERROR"/>
17
18 </configuration>
+0
-17
jdbc_jtsparser/src/test/resources-filtered/testng-it.xml less more
0 <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
1 <suite name="JTS Parser Integration Test Suite" verbose="1">
2
3 <parameter name="test.container.image-name" value="${test.container.image}"/>
4 <parameter name="test.container.port" value="${test.db.port}"/>
5 <parameter name="test.container.env.user" value="${test.db.username}"/>
6 <parameter name="test.container.env.password" value="${test.db.password}"/>
7 <parameter name="test.container.env.db" value="${test.db.name}"/>
8
9 <test name="JTS Parser Integration Tests">
10 <classes>
11 <class name="net.postgis.tools.testutils.TestContainerController"/>
12 <class name="org.postgis.jts.JtsParserTest"/>
13 </classes>
14 </test>
15
16 </suite>
88 <ignoreVersion type="regex">.*\.jre[6-7]</ignoreVersion>
99 </ignoreVersions>
1010 <rules>
11 <!-- Pin git-commit-id-plugin version to final release version before V5 until codebase migrates to Java11 -->
12 <rule groupId="pl.project13.maven" artifactId="git-commit-id-plugin">
13 <ignoreVersions>
14 <ignoreVersion type="regex">4\.9\.9</ignoreVersion>
15 </ignoreVersions>
16 </rule>
1117 <!-- Pin testng version to pre-V7 -->
12 <rule groupId="org.testng" artifactId="testng" comparisonMethod="maven">
18 <rule groupId="org.testng" artifactId="testng">
1319 <ignoreVersions>
1420 <ignoreVersion type="regex">7\..*</ignoreVersion>
1521 </ignoreVersions>
1622 </rule>
23 <!-- Ignore logback version with groovyless suffix -->
24 <rule groupId="ch.qos.logback">
25 <ignoreVersions>
26 <ignoreVersion type="regex">.*-groovyless</ignoreVersion>
27 </ignoreVersions>
28 </rule>
1729 </rules>
1830 </ruleset>
0 <ruleset xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
1 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2 xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 https://pmd.sourceforge.io/ruleset_2_0_0.xsd"
3 name="PMD Ruleset"
4 >
5 <description>
6 This ruleset is adapted from the default maven PMD plugin ruleset which can be found here:
7 https://gitbox.apache.org/repos/asf?p=maven-pmd-plugin.git;a=blob_plain;f=src/main/resources/rulesets/java/maven-pmd-plugin-default.xml;hb=HEAD
8 It contains the rules of the old (pre PMD 6.0.0) rulesets java-basic, java-empty, java-imports,
9 java-unnecessary, java-unusedcode. (see https://pmd.github.io/latest/pmd_userdocs_making_rulesets.html)
10 </description>
11 <rule ref="category/java/bestpractices.xml/AvoidUsingHardCodedIP"/>
12 <rule ref="category/java/bestpractices.xml/CheckResultSet"/>
13 <rule ref="category/java/bestpractices.xml/UnusedFormalParameter"/>
14 <rule ref="category/java/bestpractices.xml/UnusedLocalVariable"/>
15 <rule ref="category/java/bestpractices.xml/UnusedPrivateField"/>
16 <rule ref="category/java/bestpractices.xml/UnusedPrivateMethod"/>
17 <rule ref="category/java/codestyle.xml/ExtendsObject"/>
18 <rule ref="category/java/codestyle.xml/ForLoopShouldBeWhileLoop"/>
19 <rule ref="category/java/codestyle.xml/TooManyStaticImports"/>
20 <rule ref="category/java/codestyle.xml/UnnecessaryFullyQualifiedName"/>
21 <rule ref="category/java/codestyle.xml/UnnecessaryImport"/>
22 <rule ref="category/java/codestyle.xml/UnnecessaryModifier"/>
23 <rule ref="category/java/codestyle.xml/UnnecessaryReturn"/>
24 <rule ref="category/java/codestyle.xml/UselessParentheses"/>
25 <rule ref="category/java/codestyle.xml/UselessQualifiedThis"/>
26 <rule ref="category/java/design.xml/CollapsibleIfStatements"/>
27 <rule ref="category/java/design.xml/SimplifiedTernary"/>
28 <rule ref="category/java/design.xml/UselessOverridingMethod"/>
29 <rule ref="category/java/errorprone.xml/AvoidBranchingStatementAsLastInLoop"/>
30 <rule ref="category/java/errorprone.xml/AvoidDecimalLiteralsInBigDecimalConstructor"/>
31 <rule ref="category/java/errorprone.xml/AvoidMultipleUnaryOperators"/>
32 <rule ref="category/java/errorprone.xml/AvoidUsingOctalValues"/>
33 <rule ref="category/java/errorprone.xml/BrokenNullCheck"/>
34 <rule ref="category/java/errorprone.xml/CheckSkipResult"/>
35 <rule ref="category/java/errorprone.xml/ClassCastExceptionWithToArray"/>
36 <rule ref="category/java/errorprone.xml/DontUseFloatTypeForLoopIndices"/>
37 <rule ref="category/java/errorprone.xml/EmptyCatchBlock"/>
38 <rule ref="category/java/errorprone.xml/EmptyFinallyBlock"/>
39 <rule ref="category/java/errorprone.xml/EmptyIfStmt"/>
40 <rule ref="category/java/errorprone.xml/EmptyInitializer"/>
41 <rule ref="category/java/errorprone.xml/EmptyStatementBlock"/>
42 <rule ref="category/java/errorprone.xml/EmptyStatementNotInLoop"/>
43 <rule ref="category/java/errorprone.xml/EmptySwitchStatements"/>
44 <rule ref="category/java/errorprone.xml/EmptySynchronizedBlock"/>
45 <rule ref="category/java/errorprone.xml/EmptyTryBlock"/>
46 <rule ref="category/java/errorprone.xml/EmptyWhileStmt"/>
47 <rule ref="category/java/errorprone.xml/JumbledIncrementer"/>
48 <rule ref="category/java/errorprone.xml/MisplacedNullCheck"/>
49 <rule ref="category/java/errorprone.xml/OverrideBothEqualsAndHashcode"/>
50 <rule ref="category/java/errorprone.xml/ReturnFromFinallyBlock"/>
51 <rule ref="category/java/errorprone.xml/UnconditionalIfStatement"/>
52 <rule ref="category/java/errorprone.xml/UnnecessaryConversionTemporary"/>
53 <rule ref="category/java/errorprone.xml/UnusedNullCheckInEquals"/>
54 <rule ref="category/java/errorprone.xml/UselessOperationOnImmutable"/>
55 <rule ref="category/java/multithreading.xml/AvoidThreadGroup"/>
56 <rule ref="category/java/multithreading.xml/DontCallThreadRun"/>
57 <rule ref="category/java/multithreading.xml/DoubleCheckedLocking"/>
58 <rule ref="category/java/performance.xml/BigIntegerInstantiation"/>
59 <rule ref="category/java/performance.xml/BooleanInstantiation"/>
60 </ruleset>
+661
-302
pom.xml less more
33
44 <groupId>net.postgis</groupId>
55 <artifactId>postgis-java-aggregator</artifactId>
6 <version>2.5.0</version>
6 <version>2021.1.0</version>
77 <packaging>pom</packaging>
88
99 <name>PostGIS Java Project</name>
6767 </mailingLists>
6868
6969 <modules>
70 <module>postgis-jdbc</module>
71 <module>postgis-jdbc-geometry</module>
72 <module>postgis-jdbc-java2d</module>
73 <module>postgis-jdbc-jts</module>
7074 <module>tools</module>
71 <module>postgis-geometry</module>
72 <module>jdbc</module>
73 <module>jdbc_jtsparser</module>
74 <module>postgis-jdbc-java2d</module>
7575 </modules>
7676
7777 <scm>
7878 <url>https://github.com/postgis/postgis-java</url>
7979 <connection>scm:git:git://github.com/postgis/postgis-java.git</connection>
8080 <developerConnection>scm:git:git@github.com:postgis/postgis-java.git</developerConnection>
81 <tag>postgis-java-aggregator-2.5.0</tag>
81 <tag>postgis-java-aggregator-2021.1.0</tag>
8282 </scm>
8383 <issueManagement>
8484 <system>GitHub Issues</system>
8585 <url>https://github.com/postgis/postgis-java/issues</url>
8686 </issueManagement>
8787 <distributionManagement>
88 <snapshotRepository>
89 <id>ossrh</id>
90 <url>https://oss.sonatype.org/content/repositories/snapshots</url>
91 </snapshotRepository>
92 <repository>
93 <id>ossrh</id>
94 <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
95 </repository>
88 <site>
89 <id>local-staging-site</id>
90 <url>http://local-staging/</url>
91 </site>
9692 </distributionManagement>
9793
9894 <properties>
99 <checkstyle.skip>true</checkstyle.skip>
10095 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
10196 <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
102 <java.min.version>1.8</java.min.version>
97 <java.min.version>8</java.min.version>
10398 <maven.min.version>3.6</maven.min.version>
10499 <maven.test.skip>false</maven.test.skip>
105 <surefire.forkCount>1</surefire.forkCount>
106 <surefire.useSystemClassLoader>true</surefire.useSystemClassLoader>
107100 <maven.integration.test.skip>false</maven.integration.test.skip>
108101 <failsafe.forkCount>1</failsafe.forkCount>
109102 <failsafe.useSystemClassLoader>true</failsafe.useSystemClassLoader>
110 <test.container.image>postgis/postgis:12-3.0-alpine</test.container.image>
103 <surefire.forkCount>1</surefire.forkCount>
104 <surefire.useSystemClassLoader>true</surefire.useSystemClassLoader>
105 <javadoc.path>${java.home}/bin/javadoc</javadoc.path>
106 <checkstyle.skip>true</checkstyle.skip>
107 <cpd.skip>true</cpd.skip>
108 <jxr.skip>false</jxr.skip>
109 <pmd.skip>true</pmd.skip>
110 <spotbugs.skip>true</spotbugs.skip>
111 <test.container.image>postgis/postgis:13-3.1-alpine</test.container.image>
111112 <test.db.username>postgis1</test.db.username>
112113 <test.db.password>postgis1</test.db.password>
113114 <test.db.name>postgis1</test.db.name>
114115 <test.db.port>5432</test.db.port>
115116 <!-- Plugin versioning -->
116 <build-helper-maven-plugin.version>3.1.0</build-helper-maven-plugin.version>
117 <build-helper-maven-plugin.version>3.2.0</build-helper-maven-plugin.version>
117118 <directory-maven-plugin.version>0.3.1</directory-maven-plugin.version>
118 <download-maven-plugin.version>1.5.0</download-maven-plugin.version>
119 <exec-maven-plugin.version>1.6.0</exec-maven-plugin.version>
120 <git-commit-id-plugin.version>4.0.0</git-commit-id-plugin.version>
121 <jacoco-maven-plugin.version>0.8.5</jacoco-maven-plugin.version>
122 <maven-archetype-plugin.version>3.1.2</maven-archetype-plugin.version>
123 <maven-checkstyle-plugin.version>3.1.1</maven-checkstyle-plugin.version>
119 <download-maven-plugin.version>1.6.6</download-maven-plugin.version>
120 <exec-maven-plugin.version>3.0.0</exec-maven-plugin.version>
121 <git-commit-id-plugin.version>4.0.5</git-commit-id-plugin.version>
122 <jacoco-maven-plugin.version>0.8.7</jacoco-maven-plugin.version>
123 <maven-antrun-plugin.version>3.0.0</maven-antrun-plugin.version>
124 <maven-archetype-plugin.version>3.2.0</maven-archetype-plugin.version>
125 <maven-assembly-plugin.version>3.3.0</maven-assembly-plugin.version>
126 <maven-checkstyle-plugin.version>3.1.2</maven-checkstyle-plugin.version>
124127 <maven-clean-plugin.version>3.1.0</maven-clean-plugin.version>
125128 <maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
126 <maven-dependency-plugin.version>3.1.2</maven-dependency-plugin.version>
129 <maven-dependency-plugin.version>3.2.0</maven-dependency-plugin.version>
127130 <maven-deploy-plugin.version>2.8.2</maven-deploy-plugin.version>
128 <maven-ear-plugin.version>3.0.2</maven-ear-plugin.version>
131 <maven-ear-plugin.version>3.2.0</maven-ear-plugin.version>
129132 <maven-ejb-plugin.version>3.0.1</maven-ejb-plugin.version>
130 <maven-enforcer-plugin.version>1.4.1</maven-enforcer-plugin.version>
133 <maven-enforcer-plugin.version>3.0.0</maven-enforcer-plugin.version>
131134 <maven-failsafe-plugin.version>2.22.2</maven-failsafe-plugin.version>
132 <maven-gpg-plugin.version>1.6</maven-gpg-plugin.version>
135 <maven-gpg-plugin.version>3.0.1</maven-gpg-plugin.version>
133136 <maven-install-plugin.version>2.5.2</maven-install-plugin.version>
134137 <maven-jar-plugin.version>3.2.0</maven-jar-plugin.version>
135138 <maven-jarsigner-plugin.version>3.0.0</maven-jarsigner-plugin.version>
136 <maven-javadoc-plugin.version>3.2.0</maven-javadoc-plugin.version>
137 <maven-jxr-plugin.version>3.0.0</maven-jxr-plugin.version>
139 <maven-javadoc-plugin.version>3.3.0</maven-javadoc-plugin.version>
140 <maven-jxr-plugin.version>3.1.1</maven-jxr-plugin.version>
141 <maven-pmd-plugin.version>3.14.0</maven-pmd-plugin.version>
142 <maven-project-info-reports-plugin.version>3.1.2</maven-project-info-reports-plugin.version>
138143 <maven-release-plugin.version>2.5.3</maven-release-plugin.version>
139 <maven-resources-plugin.version>3.1.0</maven-resources-plugin.version>
140 <maven-site-plugin.version>3.9.0</maven-site-plugin.version>
141 <maven-shade-plugin.version>3.2.2</maven-shade-plugin.version>
144 <maven-resources-plugin.version>3.2.0</maven-resources-plugin.version>
145 <maven-shade-plugin.version>3.2.4</maven-shade-plugin.version>
146 <maven-site-plugin.version>3.9.1</maven-site-plugin.version>
142147 <maven-source-plugin.version>3.2.1</maven-source-plugin.version>
143148 <maven-surefire-plugin.version>2.22.2</maven-surefire-plugin.version>
144 <maven-war-plugin.version>3.2.3</maven-war-plugin.version>
145 <versions-maven-plugin.version>2.7</versions-maven-plugin.version>
149 <maven-surefire-report-plugin.version>2.22.2</maven-surefire-report-plugin.version>
150 <maven-war-plugin.version>3.3.1</maven-war-plugin.version>
151 <spotbugs-maven-plugin.version>4.3.0</spotbugs-maven-plugin.version>
152 <versions-maven-plugin.version>2.8.1</versions-maven-plugin.version>
146153 <!-- Dependency versions -->
147 <dependency.checkstyle.version>8.31</dependency.checkstyle.version>
148 <dependency.jts-version.version>1.16.1</dependency.jts-version.version>
149 <dependency.logback.version>1.2.3</dependency.logback.version>
150 <dependency.postgresql-jdbc.version>42.2.11</dependency.postgresql-jdbc.version>
151 <dependency.slfj.version>1.7.30</dependency.slfj.version>
152 <dependency.spatial4j.version>0.7</dependency.spatial4j.version>
153 <dependency.testcontainers.version>1.13.0</dependency.testcontainers.version>
154 <dependency.checkstyle.version>8.45</dependency.checkstyle.version>
155 <dependency.jts-version.version>1.18.1</dependency.jts-version.version>
156 <dependency.logback.version>1.2.5</dependency.logback.version>
157 <dependency.pmd.version>6.37.0</dependency.pmd.version>
158 <dependency.postgresql-jdbc.version>42.2.23</dependency.postgresql-jdbc.version>
159 <dependency.slf4j.version>1.7.32</dependency.slf4j.version>
160 <dependency.spatial4j.version>0.8</dependency.spatial4j.version>
161 <dependency.spotbugs.version>4.3.0</dependency.spotbugs.version>
162 <dependency.testcontainers.version>1.16.0</dependency.testcontainers.version>
154163 <dependency.testng.version>6.14.3</dependency.testng.version>
155164 </properties>
156165
167176 </dependencyManagement>
168177
169178 <dependencies>
170 <dependency>
171 <groupId>org.slf4j</groupId>
172 <artifactId>slf4j-api</artifactId>
173 <version>${dependency.slfj.version}</version>
174 </dependency>
175179 <dependency>
176180 <groupId>ch.qos.logback</groupId>
177181 <artifactId>logback-classic</artifactId>
184188 <version>${dependency.logback.version}</version>
185189 <scope>test</scope>
186190 </dependency>
191 <dependency>
192 <groupId>org.slf4j</groupId>
193 <artifactId>slf4j-api</artifactId>
194 <version>${dependency.slf4j.version}</version>
195 </dependency>
187196 </dependencies>
188197
189198 <build>
199 <resources>
200 <resource>
201 <directory>src/main/resources</directory>
202 </resource>
203 <resource>
204 <directory>src/main/resources-filtered</directory>
205 <filtering>true</filtering>
206 </resource>
207 </resources>
208 <testResources>
209 <testResource>
210 <directory>src/test/resources</directory>
211 </testResource>
212 <testResource>
213 <directory>src/test/resources-filtered</directory>
214 <filtering>true</filtering>
215 </testResource>
216 </testResources>
190217 <pluginManagement>
191218 <plugins>
219 <plugin>
220 <groupId>com.github.spotbugs</groupId>
221 <artifactId>spotbugs-maven-plugin</artifactId>
222 <version>${spotbugs-maven-plugin.version}</version>
223 <dependencies>
224 <dependency>
225 <groupId>com.github.spotbugs</groupId>
226 <artifactId>spotbugs</artifactId>
227 <version>${dependency.spotbugs.version}</version>
228 </dependency>
229 </dependencies>
230 <executions>
231 <execution>
232 <id>spotbugs-check</id>
233 <phase>verify</phase>
234 <goals>
235 <goal>check</goal>
236 </goals>
237 </execution>
238 </executions>
239 <configuration>
240 <skip>${spotbugs.skip}</skip>
241 </configuration>
242 </plugin>
243 <plugin>
244 <groupId>com.googlecode.maven-download-plugin</groupId>
245 <artifactId>download-maven-plugin</artifactId>
246 <version>${download-maven-plugin.version}</version>
247 </plugin>
248 <plugin>
249 <groupId>org.apache.maven.plugins</groupId>
250 <artifactId>maven-antrun-plugin</artifactId>
251 <version>${maven-antrun-plugin.version}</version>
252 </plugin>
253 <plugin>
254 <groupId>org.apache.maven.plugins</groupId>
255 <artifactId>maven-archetype-plugin</artifactId>
256 <version>${maven-archetype-plugin.version}</version>
257 </plugin>
258 <plugin>
259 <groupId>org.apache.maven.plugins</groupId>
260 <artifactId>maven-assembly-plugin</artifactId>
261 <version>${maven-assembly-plugin.version}</version>
262 </plugin>
263 <plugin>
264 <groupId>org.apache.maven.plugins</groupId>
265 <artifactId>maven-checkstyle-plugin</artifactId>
266 <version>${maven-checkstyle-plugin.version}</version>
267 <dependencies>
268 <dependency>
269 <groupId>com.puppycrawl.tools</groupId>
270 <artifactId>checkstyle</artifactId>
271 <version>${dependency.checkstyle.version}</version>
272 </dependency>
273 </dependencies>
274 <executions>
275 <execution>
276 <id>checkstyle</id>
277 <phase>validate</phase>
278 <goals>
279 <goal>check</goal>
280 </goals>
281 </execution>
282 </executions>
283 <configuration>
284 <configLocation>checkstyle.xml</configLocation>
285 <consoleOutput>true</consoleOutput>
286 <skip>${checkstyle.skip}</skip>
287 <violationSeverity>warning</violationSeverity>
288 </configuration>
289 </plugin>
290 <plugin>
291 <groupId>org.apache.maven.plugins</groupId>
292 <artifactId>maven-clean-plugin</artifactId>
293 <version>${maven-clean-plugin.version}</version>
294 </plugin>
295 <plugin>
296 <groupId>org.apache.maven.plugins</groupId>
297 <artifactId>maven-compiler-plugin</artifactId>
298 <version>${maven-compiler-plugin.version}</version>
299 <configuration>
300 <source>${java.min.version}</source>
301 <target>${java.min.version}</target>
302 </configuration>
303 </plugin>
304 <plugin>
305 <groupId>org.apache.maven.plugins</groupId>
306 <artifactId>maven-dependency-plugin</artifactId>
307 <version>${maven-dependency-plugin.version}</version>
308 </plugin>
309 <plugin>
310 <groupId>org.apache.maven.plugins</groupId>
311 <artifactId>maven-deploy-plugin</artifactId>
312 <version>${maven-deploy-plugin.version}</version>
313 </plugin>
314 <plugin>
315 <groupId>org.apache.maven.plugins</groupId>
316 <artifactId>maven-ear-plugin</artifactId>
317 <version>${maven-ear-plugin.version}</version>
318 </plugin>
319 <plugin>
320 <groupId>org.apache.maven.plugins</groupId>
321 <artifactId>maven-enforcer-plugin</artifactId>
322 <version>${maven-enforcer-plugin.version}</version>
323 <executions>
324 <execution>
325 <id>enforce-maven</id>
326 <goals>
327 <goal>enforce</goal>
328 </goals>
329 </execution>
330 </executions>
331 <configuration>
332 <rules>
333 <requireMavenVersion>
334 <version>[${maven.min.version},)</version>
335 </requireMavenVersion>
336 </rules>
337 </configuration>
338 </plugin>
339 <plugin>
340 <groupId>org.apache.maven.plugins</groupId>
341 <artifactId>maven-failsafe-plugin</artifactId>
342 <version>${maven-failsafe-plugin.version}</version>
343 <executions>
344 <execution>
345 <id>integration-tests</id>
346 <goals>
347 <goal>integration-test</goal>
348 <goal>verify</goal>
349 </goals>
350 <configuration>
351 <forkCount>${failsafe.forkCount}</forkCount>
352 <skip>${maven.integration.test.skip}</skip>
353 <suiteXmlFiles>
354 <suiteXmlFile>${project.build.testOutputDirectory}/testng-it.xml</suiteXmlFile>
355 </suiteXmlFiles>
356 <useSystemClassLoader>${failsafe.useSystemClassLoader}</useSystemClassLoader>
357 </configuration>
358 </execution>
359 </executions>
360 </plugin>
361 <plugin>
362 <groupId>org.apache.maven.plugins</groupId>
363 <artifactId>maven-gpg-plugin</artifactId>
364 <version>${maven-gpg-plugin.version}</version>
365 </plugin>
366 <plugin>
367 <groupId>org.apache.maven.plugins</groupId>
368 <artifactId>maven-install-plugin</artifactId>
369 <version>${maven-install-plugin.version}</version>
370 </plugin>
371 <plugin>
372 <groupId>org.apache.maven.plugins</groupId>
373 <artifactId>maven-jar-plugin</artifactId>
374 <version>${maven-jar-plugin.version}</version>
375 </plugin>
376 <plugin>
377 <groupId>org.apache.maven.plugins</groupId>
378 <artifactId>maven-jarsigner-plugin</artifactId>
379 <version>${maven-jarsigner-plugin.version}</version>
380 </plugin>
381 <plugin>
382 <groupId>org.apache.maven.plugins</groupId>
383 <artifactId>maven-javadoc-plugin</artifactId>
384 <version>${maven-javadoc-plugin.version}</version>
385 <configuration>
386 <javadocExecutable>${javadoc.path}</javadocExecutable>
387 <source>${java.min.version}</source>
388 </configuration>
389 </plugin>
390 <plugin>
391 <groupId>org.apache.maven.plugins</groupId>
392 <artifactId>maven-jxr-plugin</artifactId>
393 <version>${maven-jxr-plugin.version}</version>
394 </plugin>
395 <plugin>
396 <groupId>org.apache.maven.plugins</groupId>
397 <artifactId>maven-pmd-plugin</artifactId>
398 <version>${maven-pmd-plugin.version}</version>
399 <dependencies>
400 <dependency>
401 <groupId>net.sourceforge.pmd</groupId>
402 <artifactId>pmd-core</artifactId>
403 <version>${dependency.pmd.version}</version>
404 </dependency>
405 <dependency>
406 <groupId>net.sourceforge.pmd</groupId>
407 <artifactId>pmd-java</artifactId>
408 <version>${dependency.pmd.version}</version>
409 </dependency>
410 <dependency>
411 <groupId>net.sourceforge.pmd</groupId>
412 <artifactId>pmd-javascript</artifactId>
413 <version>${dependency.pmd.version}</version>
414 </dependency>
415 <dependency>
416 <groupId>net.sourceforge.pmd</groupId>
417 <artifactId>pmd-jsp</artifactId>
418 <version>${dependency.pmd.version}</version>
419 </dependency>
420 </dependencies>
421 <executions>
422 <execution>
423 <id>pmd-check</id>
424 <phase>verify</phase>
425 <goals>
426 <goal>check</goal>
427 </goals>
428 <configuration>
429 <skip>${pmd.skip}</skip>
430 </configuration>
431 </execution>
432 <execution>
433 <id>cpd-check</id>
434 <phase>verify</phase>
435 <goals>
436 <goal>cpd-check</goal>
437 </goals>
438 <configuration>
439 <skip>${cpd.skip}</skip>
440 </configuration>
441 </execution>
442 </executions>
443 <configuration>
444 <printFailingErrors>true</printFailingErrors>
445 <rulesets>
446 <!--suppress UnresolvedMavenProperty -->
447 <ruleset>file:///${multi.module.root}/pmd.xml</ruleset>
448 </rulesets>
449 </configuration>
450 </plugin>
451 <plugin>
452 <groupId>org.apache.maven.plugins</groupId>
453 <artifactId>maven-project-info-reports-plugin</artifactId>
454 <version>${maven-project-info-reports-plugin.version}</version>
455 </plugin>
456 <plugin>
457 <groupId>org.apache.maven.plugins</groupId>
458 <artifactId>maven-release-plugin</artifactId>
459 <version>${maven-release-plugin.version}</version>
460 <configuration>
461 <autoVersionSubmodules>true</autoVersionSubmodules>
462 <localCheckout>true</localCheckout>
463 <pushChanges>false</pushChanges>
464 <releaseProfiles>release-sign-artifacts,sonatype-deployment</releaseProfiles>
465 </configuration>
466 </plugin>
467 <plugin>
468 <groupId>org.apache.maven.plugins</groupId>
469 <artifactId>maven-resources-plugin</artifactId>
470 <version>${maven-resources-plugin.version}</version>
471 </plugin>
472 <plugin>
473 <groupId>org.apache.maven.plugins</groupId>
474 <artifactId>maven-shade-plugin</artifactId>
475 <version>${maven-shade-plugin.version}</version>
476 </plugin>
477 <plugin>
478 <groupId>org.apache.maven.plugins</groupId>
479 <artifactId>maven-site-plugin</artifactId>
480 <version>${maven-site-plugin.version}</version>
481 <configuration>
482 <skipDeploy>true</skipDeploy>
483 </configuration>
484 </plugin>
485 <plugin>
486 <groupId>org.apache.maven.plugins</groupId>
487 <artifactId>maven-source-plugin</artifactId>
488 <version>${maven-source-plugin.version}</version>
489 </plugin>
490 <plugin>
491 <groupId>org.apache.maven.plugins</groupId>
492 <artifactId>maven-surefire-plugin</artifactId>
493 <version>${maven-surefire-plugin.version}</version>
494 <configuration>
495 <forkCount>${surefire.forkCount}</forkCount>
496 <skip>${maven.test.skip}</skip>
497 <suiteXmlFiles>
498 <suiteXmlFile>${project.build.testOutputDirectory}/testng.xml</suiteXmlFile>
499 </suiteXmlFiles>
500 <useSystemClassLoader>${surefire.useSystemClassLoader}</useSystemClassLoader>
501 </configuration>
502 </plugin>
503 <plugin>
504 <groupId>org.apache.maven.plugins</groupId>
505 <artifactId>maven-surefire-report-plugin</artifactId>
506 <version>${maven-surefire-report-plugin.version}</version>
507 </plugin>
508 <plugin>
509 <groupId>org.apache.maven.plugins</groupId>
510 <artifactId>maven-war-plugin</artifactId>
511 <version>${maven-war-plugin.version}</version>
512 </plugin>
513 <plugin>
514 <groupId>org.codehaus.mojo</groupId>
515 <artifactId>build-helper-maven-plugin</artifactId>
516 <version>${build-helper-maven-plugin.version}</version>
517 </plugin>
518 <plugin>
519 <groupId>org.codehaus.mojo</groupId>
520 <artifactId>exec-maven-plugin</artifactId>
521 <version>${exec-maven-plugin.version}</version>
522 </plugin>
192523 <plugin>
193524 <groupId>org.codehaus.mojo</groupId>
194525 <artifactId>versions-maven-plugin</artifactId>
195526 <version>${versions-maven-plugin.version}</version>
527 <executions>
528 <execution>
529 <id>check-parent-versions-update</id>
530 <goals>
531 <goal>display-parent-updates</goal>
532 </goals>
533 <phase>validate</phase>
534 </execution>
535 </executions>
196536 <configuration>
197 <rulesUri>file:///${pom.basedir}/maven-version-rules.xml</rulesUri>
537 <!--suppress UnresolvedMavenProperty -->
538 <rulesUri>file:///${multi.module.root}/maven-version-rules.xml</rulesUri>
198539 </configuration>
199540 </plugin>
200541 <plugin>
201542 <groupId>org.commonjava.maven.plugins</groupId>
202543 <artifactId>directory-maven-plugin</artifactId>
203544 <version>${directory-maven-plugin.version}</version>
545 <executions>
546 <execution>
547 <id>multi-module-root-directory-build</id>
548 <goals>
549 <goal>directory-of</goal>
550 </goals>
551 <phase>validate</phase>
552 <configuration>
553 <property>multi.module.root</property>
554 <project>
555 <groupId>net.postgis</groupId>
556 <artifactId>postgis-java-aggregator</artifactId>
557 </project>
558 </configuration>
559 </execution>
560 <execution>
561 <id>multi-module-root-directory-site</id>
562 <goals>
563 <goal>directory-of</goal>
564 </goals>
565 <phase>pre-site</phase>
566 <configuration>
567 <property>multi.module.root</property>
568 <project>
569 <groupId>net.postgis</groupId>
570 <artifactId>postgis-java-aggregator</artifactId>
571 </project>
572 </configuration>
573 </execution>
574 </executions>
575 </plugin>
576 <plugin>
577 <groupId>org.jacoco</groupId>
578 <artifactId>jacoco-maven-plugin</artifactId>
579 <version>${jacoco-maven-plugin.version}</version>
580 <executions>
581 <execution>
582 <id>pre-unit-test</id>
583 <goals>
584 <goal>prepare-agent</goal>
585 </goals>
586 </execution>
587 <execution>
588 <id>unit-test-report</id>
589 <phase>test</phase>
590 <goals>
591 <goal>report</goal>
592 </goals>
593 </execution>
594 <execution>
595 <id>pre-integration-test</id>
596 <goals>
597 <goal>prepare-agent-integration</goal>
598 </goals>
599 <configuration>
600 <destFile>${project.build.directory}/jacoco-it.exec</destFile>
601 </configuration>
602 </execution>
603 <execution>
604 <id>integration-test-report</id>
605 <phase>integration-test</phase>
606 <goals>
607 <goal>report-integration</goal>
608 </goals>
609 <configuration>
610 <dataFile>${project.build.directory}/jacoco-it.exec</dataFile>
611 <outputDirectory>${project.reporting.outputDirectory}/jacoco-it</outputDirectory>
612 </configuration>
613 </execution>
614 </executions>
615 </plugin>
616 <plugin>
617 <groupId>pl.project13.maven</groupId>
618 <artifactId>git-commit-id-plugin</artifactId>
619 <version>${git-commit-id-plugin.version}</version>
620 <executions>
621 <execution>
622 <id>git-describe</id>
623 <goals>
624 <goal>revision</goal>
625 </goals>
626 <configuration>
627 <generateGitPropertiesFile>true</generateGitPropertiesFile>
628 <generateGitPropertiesFilename>${project.build.outputDirectory}/META-INF/git.properties</generateGitPropertiesFilename>
629 <includeOnlyProperties>
630 <property>git.branch$</property>
631 <!--<property>git.build.host$</property>-->
632 <property>git.build.number$</property>
633 <property>git.build.number.unique$</property>
634 <property>git.build.time$</property>
635 <property>git.build.user.email$</property>
636 <property>git.build.user.name$</property>
637 <property>git.build.version$</property>
638 <property>git.closest.tag.commit.count$</property>
639 <property>git.closest.tag.name$</property>
640 <property>git.commit.id$</property>
641 <property>git.commit.id.abbrev$</property>
642 <property>git.commit.user.email$</property>
643 <property>git.commit.user.name$</property>
644 <property>git.commit.time$</property>
645 <property>git.tags$</property>
646 </includeOnlyProperties>
647 </configuration>
648 </execution>
649 </executions>
204650 </plugin>
205651 </plugins>
206652 </pluginManagement>
207653 <plugins>
208654 <plugin>
209 <groupId>com.googlecode.maven-download-plugin</groupId>
210 <artifactId>download-maven-plugin</artifactId>
211 <version>${download-maven-plugin.version}</version>
212 </plugin>
213 <plugin>
214655 <groupId>org.apache.maven.plugins</groupId>
215 <artifactId>maven-archetype-plugin</artifactId>
216 <version>${maven-archetype-plugin.version}</version>
656 <artifactId>maven-enforcer-plugin</artifactId>
657 </plugin>
658 <plugin>
659 <groupId>org.commonjava.maven.plugins</groupId>
660 <artifactId>directory-maven-plugin</artifactId>
661 </plugin>
662 <plugin>
663 <groupId>com.github.spotbugs</groupId>
664 <artifactId>spotbugs-maven-plugin</artifactId>
217665 </plugin>
218666 <plugin>
219667 <groupId>org.apache.maven.plugins</groupId>
220668 <artifactId>maven-checkstyle-plugin</artifactId>
221 <version>${maven-checkstyle-plugin.version}</version>
222 <dependencies>
223 <dependency>
224 <groupId>com.puppycrawl.tools</groupId>
225 <artifactId>checkstyle</artifactId>
226 <version>${dependency.checkstyle.version}</version>
227 </dependency>
228 </dependencies>
229 <configuration>
230 <configLocation>checkstyle.xml</configLocation>
231 <consoleOutput>true</consoleOutput>
232 <skip>${checkstyle.skip}</skip>
233 <!--<suppressionsLocation>suppressions.xml</suppressionsLocation>-->
234 <violationSeverity>warning</violationSeverity>
235 </configuration>
236669 </plugin>
237670 <plugin>
238671 <groupId>org.apache.maven.plugins</groupId>
239 <artifactId>maven-clean-plugin</artifactId>
240 <version>${maven-clean-plugin.version}</version>
672 <artifactId>maven-pmd-plugin</artifactId>
241673 </plugin>
242674 <plugin>
243675 <groupId>org.apache.maven.plugins</groupId>
244 <artifactId>maven-compiler-plugin</artifactId>
245 <version>${maven-compiler-plugin.version}</version>
246 <configuration>
247 <source>${java.min.version}</source>
248 <target>${java.min.version}</target>
249 </configuration>
250 </plugin>
251 <plugin>
252 <groupId>org.apache.maven.plugins</groupId>
253 <artifactId>maven-dependency-plugin</artifactId>
254 <version>${maven-dependency-plugin.version}</version>
255 </plugin>
256 <plugin>
257 <groupId>org.apache.maven.plugins</groupId>
258 <artifactId>maven-deploy-plugin</artifactId>
259 <version>${maven-deploy-plugin.version}</version>
260 </plugin>
261 <plugin>
262 <groupId>org.apache.maven.plugins</groupId>
263 <artifactId>maven-ear-plugin</artifactId>
264 <version>${maven-ear-plugin.version}</version>
265 </plugin>
266 <plugin>
267 <groupId>org.apache.maven.plugins</groupId>
268 <artifactId>maven-enforcer-plugin</artifactId>
269 <version>${maven-enforcer-plugin.version}</version>
270 <executions>
271 <execution>
272 <id>enforce-maven</id>
273 <goals>
274 <goal>enforce</goal>
275 </goals>
276 <configuration>
277 <rules>
278 <requireMavenVersion>
279 <version>[${maven.min.version},)</version>
280 </requireMavenVersion>
281 </rules>
282 </configuration>
283 </execution>
284 </executions>
285 </plugin>
286 <plugin>
287 <groupId>org.apache.maven.plugins</groupId>
288 <artifactId>maven-failsafe-plugin</artifactId>
289 <version>${maven-failsafe-plugin.version}</version>
290 <configuration>
291 <forkCount>${failsafe.forkCount}</forkCount>
292 <skip>${maven.integration.test.skip}</skip>
293 <systemPropertyVariables>
294 <derby.stream.error.file>
295 ${project.build.directory}/derby.log
296 </derby.stream.error.file>
297 </systemPropertyVariables>
298 <useSystemClassLoader>${failsafe.useSystemClassLoader}</useSystemClassLoader>
299 </configuration>
300 </plugin>
301 <plugin>
302 <groupId>org.apache.maven.plugins</groupId>
303 <artifactId>maven-gpg-plugin</artifactId>
304 <version>${maven-gpg-plugin.version}</version>
305 </plugin>
306 <plugin>
307 <groupId>org.apache.maven.plugins</groupId>
308 <artifactId>maven-install-plugin</artifactId>
309 <version>${maven-install-plugin.version}</version>
310 </plugin>
311 <plugin>
312 <groupId>org.apache.maven.plugins</groupId>
313 <artifactId>maven-jar-plugin</artifactId>
314 <version>${maven-jar-plugin.version}</version>
315 </plugin>
316 <plugin>
317 <groupId>org.apache.maven.plugins</groupId>
318 <artifactId>maven-jarsigner-plugin</artifactId>
319 <version>${maven-jarsigner-plugin.version}</version>
320 </plugin>
676 <artifactId>maven-release-plugin</artifactId>
677 </plugin>
678 <plugin>
679 <groupId>org.jacoco</groupId>
680 <artifactId>jacoco-maven-plugin</artifactId>
681 </plugin>
682 <plugin>
683 <groupId>pl.project13.maven</groupId>
684 <artifactId>git-commit-id-plugin</artifactId>
685 </plugin>
686 </plugins>
687 </build>
688
689 <reporting>
690 <plugins>
321691 <plugin>
322692 <groupId>org.apache.maven.plugins</groupId>
323693 <artifactId>maven-javadoc-plugin</artifactId>
324 <version>${maven-javadoc-plugin.version}</version>
325 <configuration>
326 <source>${java.min.version}</source>
327 </configuration>
694 <reportSets>
695 <reportSet>
696 <id>javadoc-aggregated</id>
697 <inherited>false</inherited>
698 <reports>
699 <report>aggregate</report>
700 <report>test-aggregate</report>
701 </reports>
702 </reportSet>
703 </reportSets>
328704 </plugin>
329705 <plugin>
330706 <groupId>org.apache.maven.plugins</groupId>
331707 <artifactId>maven-jxr-plugin</artifactId>
332 <version>${maven-jxr-plugin.version}</version>
708 <reportSets>
709 <reportSet>
710 <id>jxr-aggregated</id>
711 <inherited>false</inherited>
712 <reports>
713 <report>aggregate</report>
714 <report>test-aggregate</report>
715 </reports>
716 </reportSet>
717 </reportSets>
718 </plugin>
719 <plugin>
720 <groupId>com.github.spotbugs</groupId>
721 <artifactId>spotbugs-maven-plugin</artifactId>
722 <reportSets>
723 <reportSet>
724 <id>spotbugs</id>
725 <inherited>true</inherited>
726 <configuration>
727 <skip>false</skip>
728 </configuration>
729 <reports>
730 <report>spotbugs</report>
731 </reports>
732 </reportSet>
733 </reportSets>
333734 </plugin>
334735 <plugin>
335736 <groupId>org.apache.maven.plugins</groupId>
336 <artifactId>maven-release-plugin</artifactId>
337 <version>${maven-release-plugin.version}</version>
338 <configuration>
339 <autoVersionSubmodules>true</autoVersionSubmodules>
340 <localCheckout>true</localCheckout>
341 <pushChanges>false</pushChanges>
342 <releaseProfiles>release-sign-artifacts</releaseProfiles>
343 </configuration>
737 <artifactId>maven-checkstyle-plugin</artifactId>
738 <reportSets>
739 <reportSet>
740 <id>checkstyle-aggregated</id>
741 <inherited>false</inherited>
742 <configuration>
743 <skip>false</skip>
744 </configuration>
745 <reports>
746 <report>checkstyle-aggregate</report>
747 </reports>
748 </reportSet>
749 </reportSets>
344750 </plugin>
345751 <plugin>
346752 <groupId>org.apache.maven.plugins</groupId>
347 <artifactId>maven-resources-plugin</artifactId>
348 <version>${maven-resources-plugin.version}</version>
753 <artifactId>maven-pmd-plugin</artifactId>
754 <reportSets>
755 <reportSet>
756 <id>pmd</id>
757 <inherited>false</inherited>
758 <configuration>
759 <aggregate>true</aggregate>
760 <skip>false</skip>
761 <rulesets>
762 <ruleset>pmd.xml</ruleset>
763 </rulesets>
764 </configuration>
765 <reports>
766 <report>pmd</report>
767 <report>cpd</report>
768 </reports>
769 </reportSet>
770 </reportSets>
349771 </plugin>
350772 <plugin>
351773 <groupId>org.apache.maven.plugins</groupId>
352 <artifactId>maven-site-plugin</artifactId>
353 <version>${maven-site-plugin.version}</version>
354 </plugin>
355 <plugin>
356 <groupId>org.apache.maven.plugins</groupId>
357 <artifactId>maven-shade-plugin</artifactId>
358 <version>${maven-shade-plugin.version}</version>
359 </plugin>
360 <plugin>
361 <groupId>org.apache.maven.plugins</groupId>
362 <artifactId>maven-source-plugin</artifactId>
363 <version>${maven-source-plugin.version}</version>
364 </plugin>
365 <plugin>
366 <groupId>org.apache.maven.plugins</groupId>
367 <artifactId>maven-surefire-plugin</artifactId>
368 <version>${maven-surefire-plugin.version}</version>
369 <configuration>
370 <forkCount>${surefire.forkCount}</forkCount>
371 <skip>${maven.test.skip}</skip>
372 <systemPropertyVariables>
373 <derby.stream.error.file>
374 ${project.build.directory}/derby.log
375 </derby.stream.error.file>
376 </systemPropertyVariables>
377 <useSystemClassLoader>${surefire.useSystemClassLoader}</useSystemClassLoader>
378 </configuration>
379 </plugin>
380 <plugin>
381 <groupId>org.apache.maven.plugins</groupId>
382 <artifactId>maven-war-plugin</artifactId>
383 <version>${maven-war-plugin.version}</version>
774 <artifactId>maven-surefire-report-plugin</artifactId>
775 <reportSets>
776 <reportSet>
777 <id>surefire</id>
778 <reports>
779 <report>report-only</report>
780 <report>failsafe-report-only</report>
781 </reports>
782 </reportSet>
783 </reportSets>
384784 </plugin>
385785 <plugin>
386786 <groupId>org.codehaus.mojo</groupId>
387 <artifactId>build-helper-maven-plugin</artifactId>
388 <version>${build-helper-maven-plugin.version}</version>
389 </plugin>
390 <plugin>
391 <groupId>org.codehaus.mojo</groupId>
392 <artifactId>exec-maven-plugin</artifactId>
393 <version>${exec-maven-plugin.version}</version>
787 <artifactId>versions-maven-plugin</artifactId>
788 <reportSets>
789 <reportSet>
790 <id>version-update-reports</id>
791 <reports>
792 <report>dependency-updates-report</report>
793 <report>plugin-updates-report</report>
794 <report>property-updates-report</report>
795 </reports>
796 </reportSet>
797 </reportSets>
394798 </plugin>
395799 <plugin>
396800 <groupId>org.jacoco</groupId>
397801 <artifactId>jacoco-maven-plugin</artifactId>
398 <version>${jacoco-maven-plugin.version}</version>
399 <executions>
400 <execution>
401 <id>pre-unit-test</id>
402 <goals>
403 <goal>prepare-agent</goal>
404 </goals>
405 </execution>
406 <execution>
407 <id>unit-test-report</id>
408 <phase>test</phase>
409 <goals>
410 <goal>report</goal>
411 </goals>
412 </execution>
413 <execution>
414 <id>pre-integration-test</id>
415 <goals>
416 <goal>prepare-agent-integration</goal>
417 </goals>
418 <configuration>
419 <destFile>${project.build.directory}/jacoco-it.exec</destFile>
420 </configuration>
421 </execution>
422 <execution>
423 <id>integration-test-report</id>
424 <phase>integration-test</phase>
425 <goals>
426 <goal>report-integration</goal>
427 </goals>
428 <configuration>
429 <dataFile>${project.build.directory}/jacoco-it.exec</dataFile>
430 <outputDirectory>${project.reporting.outputDirectory}/jacoco-it</outputDirectory>
431 </configuration>
432 </execution>
433 </executions>
434 </plugin>
435 <plugin>
436 <groupId>pl.project13.maven</groupId>
437 <artifactId>git-commit-id-plugin</artifactId>
438 <version>${git-commit-id-plugin.version}</version>
439 <executions>
440 <execution>
441 <id>git-describe</id>
442 <goals>
443 <goal>revision</goal>
444 </goals>
445 <configuration>
446 <generateGitPropertiesFile>true</generateGitPropertiesFile>
447 <generateGitPropertiesFilename>${project.build.outputDirectory}/META-INF/git.properties</generateGitPropertiesFilename>
448 <includeOnlyProperties>
449 <property>git.branch$</property>
450 <!--<property>git.build.host$</property>-->
451 <property>git.build.number$</property>
452 <property>git.build.number.unique$</property>
453 <property>git.build.time$</property>
454 <property>git.build.user.email$</property>
455 <property>git.build.user.name$</property>
456 <property>git.build.version$</property>
457 <property>git.closest.tag.commit.count$</property>
458 <property>git.closest.tag.name$</property>
459 <property>git.commit.id$</property>
460 <property>git.commit.id.abbrev$</property>
461 <property>git.commit.user.email$</property>
462 <property>git.commit.user.name$</property>
463 <property>git.commit.time$</property>
464 <property>git.tags$</property>
465 </includeOnlyProperties>
466 </configuration>
467 </execution>
468 </executions>
802 <reportSets>
803 <reportSet>
804 <id>test-coverage-report</id>
805 <reports>
806 <report>report</report>
807 <report>report-integration</report>
808 <report>report-aggregate</report>
809 </reports>
810 </reportSet>
811 </reportSets>
469812 </plugin>
470813 </plugins>
471 </build>
814 </reporting>
472815
473816 <profiles>
817 <!-- This profile isn't tested on windows, the path may not be specified correctly. -->
818 <profile>
819 <id>windows-javadoc</id>
820 <activation>
821 <os>
822 <family>windows</family>
823 </os>
824 </activation>
825 <properties>
826 <javadoc.path>${java.home}/bin/javadoc.exe</javadoc.path>
827 </properties>
828 </profile>
829 <profile>
830 <id>javahome-env-javadoc</id>
831 <activation>
832 <property>
833 <name>env.JAVA_HOME</name>
834 </property>
835 </activation>
836 <properties>
837 <javadoc.path>${env.JAVA_HOME}/bin/javadoc</javadoc.path>
838 </properties>
839 </profile>
474840 <profile>
475841 <id>check-versions</id>
476842 <build>
477843 <plugins>
478 <plugin>
479 <groupId>org.commonjava.maven.plugins</groupId>
480 <artifactId>directory-maven-plugin</artifactId>
481 <executions>
482 <execution>
483 <id>directory-of-property</id>
484 <goals>
485 <goal>directory-of</goal>
486 </goals>
487 <phase>validate</phase>
488 <configuration>
489 <property>multi.module.root</property>
490 <project>
491 <groupId>net.postgis</groupId>
492 <artifactId>postgis-java-aggregator</artifactId>
493 </project>
494 </configuration>
495 </execution>
496 </executions>
497 </plugin>
498844 <plugin>
499845 <groupId>org.codehaus.mojo</groupId>
500846 <artifactId>versions-maven-plugin</artifactId>
519865 </build>
520866 </profile>
521867 <!--
522 The release-sign-artifacts profile only needs activated when cutting a release for maven central.
523 It will generate additional artifacts for javadoc and source as well as GPG signatures for each artifact.
524 This profile also assumes that the properties for the gpg plugin (such as gpg.keyname and gpg.passphrase
525 are either defined in a settings.xml file or similar facility.
868 The release-sign-artifacts and sonatype deployment profiles only need activated when pushing snapshots or
869 releases to maven central. When enabled, additional artifacts will be generated for javadoc and source as well
870 as GPG signatures for each artifact. This profiles assume that the properties for the gpg plugin
871 (such as gpg.keyname and gpg.passphrase are either defined in a settings.xml file or similar facility.
526872 -->
527873 <profile>
528874 <id>release-sign-artifacts</id>
568914 </plugins>
569915 </build>
570916 </profile>
917 <profile>
918 <id>sonatype-deployment</id>
919 <distributionManagement>
920 <snapshotRepository>
921 <id>ossrh</id>
922 <url>https://oss.sonatype.org/content/repositories/snapshots</url>
923 </snapshotRepository>
924 <repository>
925 <id>ossrh</id>
926 <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
927 </repository>
928 </distributionManagement>
929 </profile>
571930
572931 <profile>
573932 <id>SkipUnitTests</id>
584943 </profile>
585944 </profiles>
586945
587 </project>
946 </project>
+0
-61
postgis-geometry/pom.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
2 <modelVersion>4.0.0</modelVersion>
3
4 <parent>
5 <groupId>net.postgis</groupId>
6 <artifactId>postgis-java-aggregator</artifactId>
7 <version>2.5.0</version>
8 </parent>
9
10 <artifactId>postgis-geometry</artifactId>
11 <version>2.5.0</version>
12 <packaging>jar</packaging>
13
14 <name>PostGIS Geometry</name>
15 <description>Geometry classes provided by PostGIS JDBC Extension</description>
16
17 <properties />
18
19 <dependencies>
20 <dependency>
21 <groupId>net.postgis.tools</groupId>
22 <artifactId>test-utils</artifactId>
23 <version>2.5.0</version>
24 <scope>test</scope>
25 </dependency>
26 </dependencies>
27
28 <build>
29 <resources>
30 <resource>
31 <directory>src/main/resources</directory>
32 <filtering>true</filtering>
33 </resource>
34 </resources>
35 <testResources>
36 <testResource>
37 <directory>src/test/resources</directory>
38 </testResource>
39 <testResource>
40 <directory>src/test/resources-filtered</directory>
41 <filtering>true</filtering>
42 </testResource>
43 </testResources>
44 <plugins>
45 <plugin>
46 <groupId>org.apache.maven.plugins</groupId>
47 <artifactId>maven-surefire-plugin</artifactId>
48 <configuration>
49 <skip>${maven.test.skip}</skip>
50 <forkCount>${surefire.forkCount}</forkCount>
51 <useSystemClassLoader>${surefire.useSystemClassLoader}</useSystemClassLoader>
52 <suiteXmlFiles>
53 <suiteXmlFile>${project.build.testOutputDirectory}/testng.xml</suiteXmlFile>
54 </suiteXmlFiles>
55 </configuration>
56 </plugin>
57 </plugins>
58 </build>
59
60 </project>
+0
-284
postgis-geometry/src/main/java/org/postgis/ComposedGeom.java less more
0 /*
1 * ComposedGeom.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - geometry model
4 *
5 * (C) 2004 Paul Ramsey, pramsey@refractions.net
6 *
7 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
8 *
9 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 */
26
27 package org.postgis;
28
29 import java.sql.SQLException;
30 import java.util.Iterator;
31 import java.util.List;
32
33 /**
34 * ComposedGeom - Abstract base class for all Geometries that are composed out
35 * of other Geometries.
36 *
37 * In fact, this currently are all Geometry subclasses except Point.
38 *
39 * @author markus.schaber@logix-tt.com
40 *
41 *
42 */
43 public abstract class ComposedGeom extends Geometry {
44 /* JDK 1.5 Serialization */
45 private static final long serialVersionUID = 0x100;
46
47 public static final Geometry[] EMPTY = new Geometry[0];
48
49 /**
50 * The Array containing the geometries
51 *
52 * This is only to be exposed by concrete subclasses, to retain type safety.
53 */
54 protected Geometry[] subgeoms = EMPTY;
55
56 /**
57 * Constructs an instance with the specified type
58 *
59 * @param type int value corresponding to the geometry type.
60 */
61 public ComposedGeom(int type) {
62 super(type);
63 }
64
65 public Geometry getSubGeometry(int index) {
66 return subgeoms[index];
67 }
68
69 public int numGeoms() {
70 return subgeoms.length;
71 }
72
73 protected ComposedGeom(int type, Geometry[] geoms) {
74 this(type);
75 this.subgeoms = geoms;
76 if (geoms.length > 0) {
77 dimension = geoms[0].dimension;
78 haveMeasure = geoms[0].haveMeasure;
79 } else {
80 dimension = 0;
81 }
82 }
83
84 protected ComposedGeom(int type, String value, boolean haveM) throws SQLException {
85 super(type);
86 value = initSRID(value);
87
88 String typestring = getTypeString();
89 if (value.indexOf(typestring) == 0) {
90 int pfxlen = typestring.length();
91 if (value.charAt(pfxlen) == 'M') {
92 pfxlen += 1;
93 haveM = true;
94 }
95 value = value.substring(pfxlen).trim();
96 } else if (value.charAt(0) != '(') {
97 // we are neigher inner nor outer rep.
98 throw new SQLException("Error parsing a " + typestring + " out of " + value);
99 }
100 if (value.equals("(EMPTY)")) {
101 // Special case for PostGIS 0.X style empty geometry collections
102 // (which are not OpenGIS compliant)
103 return;
104 }
105
106 String valueNoParans = GeometryTokenizer.removeLeadingAndTrailingStrings(value, "(", ")");
107 List<String> tokens = GeometryTokenizer.tokenize(valueNoParans, ',');
108
109 int subgeomcount = tokens.size();
110 subgeoms = createSubGeomArray(subgeomcount);
111 for (int p = 0; p < subgeomcount; p++) {
112 subgeoms[p] = createSubGeomInstance(tokens.get(p), haveM);
113 }
114 dimension = subgeoms[0].dimension;
115 // fetch haveMeasure from sub-point because haveM does only work with
116 // 2d+M, not with 3d+M geometries
117 haveMeasure = subgeoms[0].haveMeasure;
118 }
119
120 /**
121 * Return the appropriate instance of the sub-geometry - this encapsulates
122 * subclass specific constructor calls
123 *
124 * @param token The token containing the value for the sub-geometry
125 * @param haveM flag to indicate the existence of a measure
126 * @return the new sub-geometry
127 * @throws SQLException if a SQLException is thrown
128 */
129 protected abstract Geometry createSubGeomInstance(String token, boolean haveM) throws SQLException;
130
131 /**
132 * Return the appropriate instance of the sub-geometry array - this
133 * encapsulates subclass specific array instantiation
134 *
135 * @param size number of elements in the array
136 * @return Geometry array corresponding to the sub-geometry
137 */
138 protected abstract Geometry[] createSubGeomArray(int size);
139
140 protected boolean equalsintern(Geometry other) {
141 // Can be assumed to be the same subclass of Geometry, so it must be a
142 // ComposedGeom, too.
143 ComposedGeom cother = (ComposedGeom) other;
144
145 if (cother.subgeoms == null && subgeoms == null) {
146 return true;
147 } else if (cother.subgeoms == null || subgeoms == null) {
148 return false;
149 } else if (cother.subgeoms.length != subgeoms.length) {
150 return false;
151 } else if (subgeoms.length == 0) {
152 return true;
153 } else {
154 for (int i = 0; i < subgeoms.length; i++) {
155 if (!cother.subgeoms[i].equalsintern(this.subgeoms[i])) {
156 return false;
157 }
158 }
159 }
160 return true;
161 }
162
163 public int numPoints() {
164 if ((subgeoms == null) || (subgeoms.length == 0)) {
165 return 0;
166 } else {
167 int result = 0;
168 for (int i = 0; i < subgeoms.length; i++) {
169 result += subgeoms[i].numPoints();
170 }
171 return result;
172 }
173 }
174
175 public Point getPoint(int n) {
176 if (n < 0) {
177 throw new ArrayIndexOutOfBoundsException("Negative index not allowed");
178 } else if ((subgeoms == null) || (subgeoms.length == 0)) {
179 throw new ArrayIndexOutOfBoundsException("Empty Geometry has no Points!");
180 } else {
181 for (int i = 0; i < subgeoms.length; i++) {
182
183 Geometry current = subgeoms[i];
184 int np = current.numPoints();
185 if (n < np) {
186 return current.getPoint(n);
187 } else {
188 n -= np;
189 }
190 }
191 throw new ArrayIndexOutOfBoundsException("Index too large!");
192 }
193 }
194
195 /**
196 * Optimized version
197 */
198 public Point getLastPoint() {
199 if ((subgeoms == null) || (subgeoms.length == 0)) {
200 throw new ArrayIndexOutOfBoundsException("Empty Geometry has no Points!");
201 } else {
202 return subgeoms[subgeoms.length - 1].getLastPoint();
203 }
204 }
205
206 /**
207 * Optimized version
208 */
209 public Point getFirstPoint() {
210 if ((subgeoms == null) || (subgeoms.length == 0)) {
211 throw new ArrayIndexOutOfBoundsException("Empty Geometry has no Points!");
212 } else {
213 return subgeoms[0].getFirstPoint();
214 }
215 }
216
217 public Iterator iterator() {
218 return java.util.Arrays.asList(subgeoms).iterator();
219 }
220
221 public boolean isEmpty() {
222 return (subgeoms == null) || (subgeoms.length == 0);
223 }
224
225 protected void mediumWKT(StringBuffer sb) {
226 if ((subgeoms == null) || (subgeoms.length == 0)) {
227 sb.append(" EMPTY");
228 } else {
229 sb.append('(');
230 innerWKT(sb);
231 sb.append(')');
232 }
233 }
234
235 protected void innerWKT(StringBuffer sb) {
236 subgeoms[0].mediumWKT(sb);
237 for (int i = 1; i < subgeoms.length; i++) {
238 sb.append(',');
239 subgeoms[i].mediumWKT(sb);
240 }
241 }
242
243 // Hashing - still buggy!
244 boolean nohash = true;
245 int hashcode = 0;
246
247 public int hashCode() {
248 if (nohash) {
249 hashcode = super.hashCode() ^ subgeoms.hashCode();
250 nohash = false;
251 }
252 return hashcode;
253 }
254
255 public boolean checkConsistency() {
256 if (super.checkConsistency()) {
257 if (isEmpty()) {
258 return true;
259 }
260 // cache to avoid getMember opcode
261 int _dimension = this.dimension;
262 boolean _haveMeasure = this.haveMeasure;
263 int _srid = this.srid;
264 for (int i = 0; i < subgeoms.length; i++) {
265 Geometry sub = subgeoms[i];
266 if (!(sub.checkConsistency() && sub.dimension == _dimension
267 && sub.haveMeasure == _haveMeasure && sub.srid == _srid)) {
268 return false;
269 }
270 }
271 return true;
272 } else {
273 return false;
274 }
275 }
276
277 public void setSrid(int srid) {
278 super.setSrid(srid);
279 for (int i = 0; i < subgeoms.length; i++) {
280 subgeoms[i].setSrid(srid);
281 }
282 }
283 }
+0
-379
postgis-geometry/src/main/java/org/postgis/Geometry.java less more
0 /*
1 * Geometry.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - geometry model
4 *
5 * (C) 2004 Paul Ramsey, pramsey@refractions.net
6 *
7 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
8 *
9 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 */
26
27 package org.postgis;
28
29 import java.io.Serializable;
30
31 /** The base class of all geometries */
32 public abstract class Geometry implements Serializable {
33 /* JDK 1.5 Serialization */
34 private static final long serialVersionUID = 0x100;
35
36 // OpenGIS Geometry types as defined in the OGC WKB Spec
37 // (May we replace this with an ENUM as soon as JDK 1.5
38 // has gained widespread usage?)
39
40 /** Fake type for linear ring */
41 public static final int LINEARRING = 0;
42 /**
43 * The OGIS geometry type number for points.
44 */
45 public static final int POINT = 1;
46
47 /**
48 * The OGIS geometry type number for lines.
49 */
50 public static final int LINESTRING = 2;
51
52 /**
53 * The OGIS geometry type number for polygons.
54 */
55 public static final int POLYGON = 3;
56
57 /**
58 * The OGIS geometry type number for aggregate points.
59 */
60 public static final int MULTIPOINT = 4;
61
62 /**
63 * The OGIS geometry type number for aggregate lines.
64 */
65 public static final int MULTILINESTRING = 5;
66
67 /**
68 * The OGIS geometry type number for aggregate polygons.
69 */
70 public static final int MULTIPOLYGON = 6;
71
72 /**
73 * The OGIS geometry type number for feature collections.
74 */
75 public static final int GEOMETRYCOLLECTION = 7;
76
77 public static final String[] ALLTYPES = new String[] {
78 "", // internally used LinearRing does not have any text in front of
79 // it
80 "POINT", "LINESTRING", "POLYGON", "MULTIPOINT", "MULTILINESTRING",
81 "MULTIPOLYGON", "GEOMETRYCOLLECTION" };
82
83 /**
84 * The Text representations of the geometry types
85 *
86 * @param type int value of the type to lookup
87 * @return String reprentation of the type.
88 */
89 public static String getTypeString(int type) {
90 if (type >= 0 && type <= 7) {
91 return ALLTYPES[type];
92 } else {
93 throw new IllegalArgumentException("Unknown Geometry type" + type);
94 }
95 }
96
97 // Properties common to all geometries
98 /**
99 * The dimensionality of this feature (2,3)
100 */
101 public int dimension;
102
103 /**
104 * Do we have a measure (4th dimension)
105 */
106 public boolean haveMeasure = false;
107
108 /**
109 * The OGIS geometry type of this feature. this is final as it never
110 * changes, it is bound to the subclass of the instance.
111 */
112 public final int type;
113
114 /**
115 * Official UNKNOWN srid value
116 */
117 public final static int UNKNOWN_SRID = 0;
118
119 /**
120 * The spacial reference system id of this geometry, default is no srid
121 */
122 public int srid = UNKNOWN_SRID;
123
124 /**
125 * Parse a SRID value, anything {@code <= 0} is unknown
126 *
127 * @param srid the SRID to parse
128 * @return parsed SRID value
129 */
130 public static int parseSRID(int srid) {
131 if (srid < 0) {
132 /* TODO: raise a warning ? */
133 srid = 0;
134 }
135 return srid;
136 }
137
138 /**
139 * Constructor for subclasses
140 *
141 * @param type
142 * has to be given by all subclasses.
143 */
144 protected Geometry(int type) {
145 this.type = type;
146 }
147
148 /**
149 * java.lang.Object hashCode implementation
150 */
151 public int hashCode() {
152 return dimension | (type * 4) | (srid * 32);
153 }
154
155 /**
156 * java.lang.Object equals implementation
157 *
158 * @param other geometry to compare
159 * @return true if equal, false otherwise
160 */
161 public boolean equals(Object other) {
162 return (other != null) && (other instanceof Geometry)
163 && equals((Geometry) other);
164 }
165
166 /**
167 * geometry specific equals implementation - only defined for non-null
168 * values
169 *
170 * @param other geometry to compare
171 * @return true if equal, false otherwise
172 */
173 public boolean equals(Geometry other) {
174 return (other != null) && (this.dimension == other.dimension)
175 && (this.type == other.type) && (this.srid == other.srid)
176 && (this.haveMeasure == other.haveMeasure)
177 && other.getClass().equals(this.getClass())
178 && this.equalsintern(other);
179 }
180
181 /**
182 * Whether test coordinates for geometry - subclass specific code
183 *
184 * Implementors can assume that dimensin, type, srid and haveMeasure are
185 * equal, other != null and other is the same subclass.
186 *
187 * @param other geometry to compare
188 * @return true if equal, false otherwise
189 */
190 protected abstract boolean equalsintern(Geometry other);
191
192 /**
193 * Return the number of Points of the geometry
194 *
195 * @return number of points in the geometry
196 */
197 public abstract int numPoints();
198
199 /**
200 * Get the nth Point of the geometry
201 *
202 * @param n the index of the point, from 0 to numPoints()-1;
203 * @return nth point in the geometry
204 * @throws ArrayIndexOutOfBoundsException in case of an emtpy geometry or bad index.
205 */
206 public abstract Point getPoint(int n);
207
208 /**
209 * Same as getPoint(0);
210 *
211 * @return the initial Point in this geometry
212 */
213 public abstract Point getFirstPoint();
214
215 /**
216 * Same as getPoint(numPoints()-1);
217 *
218 * @return the final Point in this geometry
219 */
220 public abstract Point getLastPoint();
221
222 /**
223 * The OGIS geometry type number of this geometry.
224 *
225 * @return int value representation for the type of this geometry
226 */
227 public int getType() {
228 return this.type;
229 }
230
231 /**
232 * Return the Type as String
233 *
234 * @return String representation for the type of this geometry
235 */
236 public String getTypeString() {
237 return getTypeString(this.type);
238 }
239
240 /**
241 * Returns whether we have a measure
242 *
243 * @return true if the geometry has a measure, false otherwise
244 */
245 public boolean isMeasured() {
246 return haveMeasure;
247 }
248
249 /**
250 * Queries the number of geometric dimensions of this geometry. This does
251 * not include measures, as opposed to the server.
252 *
253 * @return The dimensionality (eg, 2D or 3D) of this geometry.
254 */
255 public int getDimension() {
256 return this.dimension;
257 }
258
259 /**
260 * The OGIS geometry type number of this geometry.
261 *
262 * @return the SRID of this geometry
263 */
264 public int getSrid() {
265 return this.srid;
266 }
267
268 /**
269 * Recursively sets the srid on this geometry and all contained
270 * subgeometries
271 *
272 * @param srid the SRID for this geometry
273 */
274 public void setSrid(int srid) {
275 this.srid = srid;
276 }
277
278 public String toString() {
279 StringBuffer sb = new StringBuffer();
280 if (srid != UNKNOWN_SRID) {
281 sb.append("SRID=");
282 sb.append(srid);
283 sb.append(';');
284 }
285 outerWKT(sb, true);
286 return sb.toString();
287 }
288
289 /**
290 * Render the WKT version of this Geometry (without SRID) into the given
291 * StringBuffer.
292 *
293 * @param sb StringBuffer to render into
294 * @param putM flag to indicate if the M character should be used.
295 */
296 public void outerWKT(StringBuffer sb, boolean putM) {
297 sb.append(getTypeString());
298 if (putM && haveMeasure && dimension == 2) {
299 sb.append('M');
300 }
301 mediumWKT(sb);
302 }
303
304 public final void outerWKT(StringBuffer sb) {
305 outerWKT(sb, true);
306 }
307
308 /**
309 * Render the WKT without the type name, but including the brackets into the
310 * StringBuffer
311 *
312 * @param sb StringBuffer to render into
313 */
314 protected void mediumWKT(StringBuffer sb) {
315 sb.append('(');
316 innerWKT(sb);
317 sb.append(')');
318 }
319
320 /**
321 * Render the "inner" part of the WKT (inside the brackets) into the
322 * StringBuffer.
323 *
324 * @param SB StringBuffer to render into
325 */
326 protected abstract void innerWKT(StringBuffer SB);
327
328 /**
329 * backwards compatibility method
330 *
331 * @return String representation of the value for the geometry.
332 */
333 public String getValue() {
334 StringBuffer sb = new StringBuffer();
335 mediumWKT(sb);
336 return sb.toString();
337 }
338
339 /**
340 * Do some internal consistency checks on the geometry.
341 *
342 * Currently, all Geometries must have a valid dimension (2 or 3) and a
343 * valid type. 2-dimensional Points must have Z=0.0, as well as non-measured
344 * Points must have m=0.0. Composed geometries must have all equal SRID,
345 * dimensionality and measures, as well as that they do not contain NULL or
346 * inconsistent subgeometries.
347 *
348 * BinaryParser and WKTParser should only generate consistent geometries.
349 * BinaryWriter may produce invalid results on inconsistent geometries.
350 *
351 * @return true if all checks are passed.
352 */
353 public boolean checkConsistency() {
354 return (dimension >= 2 && dimension <= 3) && (type >= 0 && type <= 7);
355 }
356
357 /**
358 * Splits the SRID=4711; part of a EWKT rep if present and sets the srid.
359 *
360 * @param value String value to extract the SRID from
361 * @return value without the SRID=4711; part
362 */
363 protected String initSRID(String value) {
364 value = value.trim();
365 if (value.startsWith("SRID=")) {
366 int index = value.indexOf(';', 5); // sridprefix length is 5
367 if (index == -1) {
368 throw new IllegalArgumentException(
369 "Error parsing Geometry - SRID not delimited with ';' ");
370 } else {
371 this.srid = Integer.parseInt(value.substring(5, index));
372 return value.substring(index + 1).trim();
373 }
374 } else {
375 return value;
376 }
377 }
378 }
+0
-115
postgis-geometry/src/main/java/org/postgis/GeometryBuilder.java less more
0 package org.postgis;
1
2
3 import org.postgis.binary.BinaryParser;
4
5 import java.sql.SQLException;
6
7
8 /**
9 * Builds geometry instances.
10 *
11 * Note: This class contains the word "builder" but does NOT implement the builder pattern (yet).
12 *
13 * @author Phillip Ross
14 */
15 public class GeometryBuilder {
16
17 /** The prefix that indicates SRID presence */
18 public static final String SRIDPREFIX = "SRID=";
19
20
21 public static Geometry geomFromString(String value) throws SQLException {
22 return geomFromString(value, false);
23 }
24
25 public static Geometry geomFromString(String value, boolean haveM) throws SQLException {
26 BinaryParser bp = new BinaryParser();
27
28 return geomFromString(value, bp, haveM);
29 }
30
31 /**
32 * Maybe we could add more error checking here?
33 *
34 * @param value String representing the geometry
35 * @param bp BinaryParser to use whe parsing
36 * @return Geometry object parsed from the specified string value
37 * @throws SQLException when a SQLException occurs
38 */
39 public static Geometry geomFromString(String value, BinaryParser bp) throws SQLException {
40 return geomFromString(value, bp, false);
41 }
42
43 public static Geometry geomFromString(String value, BinaryParser bp, boolean haveM)
44 throws SQLException {
45 value = value.trim();
46
47 int srid = Geometry.UNKNOWN_SRID;
48
49 if (value.startsWith(SRIDPREFIX)) {
50 // break up geometry into srid and wkt
51 String[] parts = splitSRID(value);
52 value = parts[1].trim();
53 srid = Geometry.parseSRID(Integer.parseInt(parts[0].substring(5)));
54 }
55
56 Geometry result;
57 if (value.startsWith("00") || value.startsWith("01")) {
58 result = bp.parse(value);
59 } else if (value.endsWith("EMPTY")) {
60 // We have a standard conforming representation for an empty
61 // geometry which is to be parsed as an empty GeometryCollection.
62 result = new GeometryCollection();
63 } else if (value.startsWith("MULTIPOLYGON")) {
64 result = new MultiPolygon(value, haveM);
65 } else if (value.startsWith("MULTILINESTRING")) {
66 result = new MultiLineString(value, haveM);
67 } else if (value.startsWith("MULTIPOINT")) {
68 result = new MultiPoint(value, haveM);
69 } else if (value.startsWith("POLYGON")) {
70 result = new Polygon(value, haveM);
71 } else if (value.startsWith("LINESTRING")) {
72 result = new LineString(value, haveM);
73 } else if (value.startsWith("POINT")) {
74 result = new Point(value, haveM);
75 } else if (value.startsWith("GEOMETRYCOLLECTION")) {
76 result = new GeometryCollection(value, haveM);
77 } else {
78 throw new SQLException("Unknown type: " + value);
79 }
80
81 if (srid != Geometry.UNKNOWN_SRID) {
82 result.srid = srid;
83 }
84
85 return result;
86 }
87
88
89 /**
90 * Splits a String at the first occurrence of border character.
91 *
92 * Poor man's String.split() replacement, as String.split() was invented at
93 * jdk1.4, and the Debian PostGIS Maintainer had problems building the woody
94 * backport of his package using DFSG-free compilers. In all the cases we
95 * used split() in the org.postgis package, we only needed to split at the
96 * first occurence, and thus this code could even be faster.
97 *
98 * @param whole the String to be split
99 * @return String array containing the split elements
100 * @throws SQLException when a SQLException occurrs
101 */
102 public static String[] splitSRID(String whole) throws SQLException {
103 int index = whole.indexOf(';', 5); // sridprefix length is 5
104 if (index == -1) {
105 throw new SQLException("Error parsing Geometry - SRID not delimited with ';' ");
106 } else {
107 return new String[]{
108 whole.substring(0, index),
109 whole.substring(index + 1)};
110 }
111 }
112
113
114 }
+0
-82
postgis-geometry/src/main/java/org/postgis/GeometryCollection.java less more
0 /*
1 * GeometryCollection.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - geometry model
4 *
5 * (C) 2004 Paul Ramsey, pramsey@refractions.net
6 *
7 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
8 *
9 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 */
26
27 package org.postgis;
28
29 import java.sql.SQLException;
30
31
32 /**
33 * Geometry Collection class WARNING: Currently only implements empty
34 * collections
35 *
36 * @author markus.schaber@logix-tt.com
37 *
38 */
39
40 public class GeometryCollection extends ComposedGeom {
41 /* JDK 1.5 Serialization */
42 private static final long serialVersionUID = 0x100;
43
44 public static final String GeoCollID = "GEOMETRYCOLLECTION";
45
46 public GeometryCollection() {
47 super(GEOMETRYCOLLECTION);
48 }
49
50 public GeometryCollection(Geometry[] geoms) {
51 super(GEOMETRYCOLLECTION, geoms);
52 }
53
54 public GeometryCollection(String value) throws SQLException {
55 this(value, false);
56 }
57
58 public GeometryCollection(String value, boolean haveM) throws SQLException {
59 super(GEOMETRYCOLLECTION, value, haveM);
60 }
61
62 protected Geometry[] createSubGeomArray(int ngeoms) {
63 return new Geometry[ngeoms];
64 }
65
66 protected Geometry createSubGeomInstance(String token, boolean haveM) throws SQLException {
67 return GeometryBuilder.geomFromString(token, haveM);
68 }
69
70 protected void innerWKT(StringBuffer SB) {
71 subgeoms[0].outerWKT(SB, true);
72 for (int i = 1; i < subgeoms.length; i++) {
73 SB.append(',');
74 subgeoms[i].outerWKT(SB, true);
75 }
76 }
77
78 public Geometry[] getGeometries() {
79 return subgeoms;
80 }
81 }
+0
-76
postgis-geometry/src/main/java/org/postgis/GeometryTokenizer.java less more
0 /*
1 * GeometryTokenizer.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - geometry model
4 *
5 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 *
21 */
22
23 package org.postgis;
24
25
26 import java.util.ArrayList;
27 import java.util.List;
28 import java.util.Stack;
29
30
31 public class GeometryTokenizer {
32
33
34 public static List<String> tokenize(String string, char delimiter) {
35 List<String> tokens = new ArrayList<>();
36 Stack<Character> stack = new Stack<>();
37 int consumed = 0;
38 for (int position = 0; position < string.length(); position++) {
39 char character = string.charAt(position);
40 if ((character == '(') || (character == '[')) {
41 stack.push(character);
42 } else if (((character == ')') && (stack.peek() == '(')) ||
43 ((character == ']') && (stack.peek() == '['))
44 ) {
45 stack.pop();
46 }
47 if ((character == delimiter) && (stack.size() == 0)) {
48 tokens.add(string.substring(consumed, position));
49 consumed = position + 1;
50 }
51 }
52 if (consumed < string.length()) {
53 tokens.add(string.substring(consumed));
54 }
55 return tokens;
56 }
57
58
59 public static String removeLeadingAndTrailingStrings(String string, String leadingString, String trailingString) {
60 int startIndex = string.indexOf(leadingString);
61 if (startIndex == -1) {
62 startIndex = 0;
63 } else {
64 startIndex += leadingString.length();
65 }
66
67 int endIndex = string.lastIndexOf(trailingString);
68 if (endIndex == -1) {
69 endIndex = string.length();
70 }
71 return string.substring(startIndex, endIndex);
72 }
73
74
75 }
+0
-103
postgis-geometry/src/main/java/org/postgis/LineString.java less more
0 /*
1 * LineString.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - geometry model
4 *
5 * (C) 2004 Paul Ramsey, pramsey@refractions.net
6 *
7 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
8 *
9 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 */
26
27 package org.postgis;
28
29 import java.sql.SQLException;
30
31 public class LineString extends PointComposedGeom {
32 /* JDK 1.5 Serialization */
33 private static final long serialVersionUID = 0x100;
34
35 double len = -1.;
36
37 public LineString() {
38 super(LINESTRING);
39 }
40
41 public LineString(Point[] points) {
42 super(LINESTRING, points);
43 }
44
45 public LineString(String value) throws SQLException {
46 super(LINESTRING, value);
47 }
48
49 public LineString(String value, boolean haveM) throws SQLException {
50 super(LINESTRING, value, haveM);
51 }
52
53 public LineString reverse() {
54 Point[] points = this.getPoints();
55 int l = points.length;
56 int i, j;
57 Point[] p = new Point[l];
58 for (i = 0, j = l - 1; i < l; i++, j--) {
59 p[i] = points[j];
60 }
61 return new LineString(p);
62 }
63
64 public LineString concat(LineString other) {
65 Point[] points = this.getPoints();
66 Point[] opoints = other.getPoints();
67
68 boolean cutPoint = this.getLastPoint() == null
69 || this.getLastPoint().equals(other.getFirstPoint());
70 int count = points.length + opoints.length - (cutPoint ? 1 : 0);
71 Point[] p = new Point[count];
72
73 // Maybe we should use System.arrayCopy here?
74 int i, j;
75 for (i = 0; i < points.length; i++) {
76 p[i] = points[i];
77 }
78 if (!cutPoint) {
79 p[i++] = other.getFirstPoint();
80 }
81 for (j = 1; j < opoints.length; j++, i++) {
82 p[i] = opoints[j];
83 }
84 return new LineString(p);
85 }
86
87 public double length() {
88 if (len < 0) {
89 Point[] points = this.getPoints();
90 if ((points == null) || (points.length < 2)) {
91 len = 0;
92 } else {
93 double sum = 0;
94 for (int i = 1; i < points.length; i++) {
95 sum += points[i - 1].distance(points[i]);
96 }
97 len = sum;
98 }
99 }
100 return len;
101 }
102 }
+0
-80
postgis-geometry/src/main/java/org/postgis/LinearRing.java less more
0 /*
1 * LinearRing.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - geometry model
4 *
5 * (C) 2004 Paul Ramsey, pramsey@refractions.net
6 *
7 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
8 *
9 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 */
26
27 package org.postgis;
28
29 import java.sql.SQLException;
30 import java.util.List;
31
32
33 /**
34 * This represents the LinearRing GIS datatype. This type is used to construct
35 * the polygon types, but is not stored or retrieved directly from the database.
36 */
37 public class LinearRing extends PointComposedGeom {
38 /* JDK 1.5 Serialization */
39 private static final long serialVersionUID = 0x100;
40
41 public LinearRing(Point[] points) {
42 super(LINEARRING, points);
43 }
44
45 /**
46 * This is called to construct a LinearRing from the PostGIS string
47 * representation of a ring.
48 *
49 * @param value Definition of this ring in the PostGIS string format.
50 * @throws SQLException when a SQLException occurs
51 */
52 public LinearRing(String value) throws SQLException {
53 this(value, false);
54 }
55
56 /**
57 * @param value The text representation of this LinearRing
58 * @param haveM Hint whether we have a measure. This is given to us by other
59 * "parent" Polygon, and is passed further to our parent.
60 * @throws SQLException when a SQLException occurs
61 */
62
63 protected LinearRing(String value, boolean haveM) throws SQLException {
64 super(LINEARRING);
65 String valueNoParans = GeometryTokenizer.removeLeadingAndTrailingStrings(value.trim(), "(", ")");
66 List<String> tokens = GeometryTokenizer.tokenize(valueNoParans, ',');
67 int npoints = tokens.size();
68 Point[] points = new Point[npoints];
69 for (int p = 0; p < npoints; p++) {
70 points[p] = new Point(tokens.get(p), haveM);
71 }
72 this.dimension = points[0].dimension;
73 // fetch haveMeasure from subpoint because haveM does only work with
74 // 2d+M, not with 3d+M geometries
75 this.haveMeasure = points[0].haveMeasure;
76 this.subgeoms = points;
77 }
78
79 }
+0
-97
postgis-geometry/src/main/java/org/postgis/MultiLineString.java less more
0 /*
1 * MultiLineString.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - geometry model
4 *
5 * (C) 2004 Paul Ramsey, pramsey@refractions.net
6 *
7 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
8 *
9 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 */
26
27 package org.postgis;
28
29 import java.sql.SQLException;
30
31 public class MultiLineString extends ComposedGeom {
32 /* JDK 1.5 Serialization */
33 private static final long serialVersionUID = 0x100;
34
35 double len = -1;
36
37 public int hashCode() {
38 return super.hashCode() ^ (int) this.length();
39 }
40
41 public MultiLineString() {
42 super(MULTILINESTRING);
43 }
44
45 public MultiLineString(LineString[] lines) {
46 super(MULTILINESTRING, lines);
47 }
48
49 public MultiLineString(String value) throws SQLException {
50 this(value, false);
51 }
52
53 public MultiLineString(String value, boolean haveM) throws SQLException {
54 super(MULTILINESTRING, value, haveM);
55 }
56
57 protected Geometry createSubGeomInstance(String token, boolean haveM) throws SQLException {
58 return new LineString(token, haveM);
59 }
60
61 protected Geometry[] createSubGeomArray(int nlines) {
62 return new LineString[nlines];
63 }
64
65 public int numLines() {
66 return subgeoms.length;
67 }
68
69 public LineString[] getLines() {
70 return (LineString[]) subgeoms.clone();
71 }
72
73 public LineString getLine(int idx) {
74 if (idx >= 0 & idx < subgeoms.length) {
75 return (LineString) subgeoms[idx];
76 } else {
77 return null;
78 }
79 }
80
81 public double length() {
82 if (len < 0) {
83 LineString[] lines = (LineString[]) subgeoms;
84 if (lines.length < 1) {
85 len = 0;
86 } else {
87 double sum = 0;
88 for (int i = 0; i < lines.length; i++) {
89 sum += lines[i].length();
90 }
91 len = sum;
92 }
93 }
94 return len;
95 }
96 }
+0
-51
postgis-geometry/src/main/java/org/postgis/MultiPoint.java less more
0 /*
1 * MultiPoint.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - geometry model
4 *
5 * (C) 2004 Paul Ramsey, pramsey@refractions.net
6 *
7 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
8 *
9 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 */
26
27 package org.postgis;
28
29 import java.sql.SQLException;
30
31 public class MultiPoint extends PointComposedGeom {
32 /* JDK 1.5 Serialization */
33 private static final long serialVersionUID = 0x100;
34
35 public MultiPoint() {
36 super(MULTIPOINT);
37 }
38
39 public MultiPoint(Point[] points) {
40 super(MULTIPOINT, points);
41 }
42
43 public MultiPoint(String value) throws SQLException {
44 this(value, false);
45 }
46
47 protected MultiPoint(String value, boolean haveM) throws SQLException {
48 super(MULTIPOINT, value, haveM);
49 }
50 }
+0
-75
postgis-geometry/src/main/java/org/postgis/MultiPolygon.java less more
0 /*
1 * MultiPolygon.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - geometry model
4 *
5 * (C) 2004 Paul Ramsey, pramsey@refractions.net
6 *
7 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
8 *
9 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 */
26
27 package org.postgis;
28
29 import java.sql.SQLException;
30
31 public class MultiPolygon extends ComposedGeom {
32 /* JDK 1.5 Serialization */
33 private static final long serialVersionUID = 0x100;
34
35 public MultiPolygon() {
36 super(MULTIPOLYGON);
37 }
38
39 public MultiPolygon(Polygon[] polygons) {
40 super(MULTIPOLYGON, polygons);
41 }
42
43 public MultiPolygon(String value) throws SQLException {
44 this(value, false);
45 }
46
47 protected MultiPolygon(String value, boolean haveM) throws SQLException {
48 super(MULTIPOLYGON, value, haveM);
49 }
50
51 protected Geometry[] createSubGeomArray(int npolygons) {
52 return new Polygon[npolygons];
53 }
54
55 protected Geometry createSubGeomInstance(String token, boolean haveM) throws SQLException {
56 return new Polygon(token, haveM);
57 }
58
59 public int numPolygons() {
60 return subgeoms.length;
61 }
62
63 public Polygon getPolygon(int idx) {
64 if (idx >= 0 & idx < subgeoms.length) {
65 return (Polygon) subgeoms[idx];
66 } else {
67 return null;
68 }
69 }
70
71 public Polygon[] getPolygons() {
72 return (Polygon[]) subgeoms;
73 }
74 }
+0
-302
postgis-geometry/src/main/java/org/postgis/Point.java less more
0 /*
1 * Point.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - geometry model
4 *
5 * (C) 2004 Paul Ramsey, pramsey@refractions.net
6 *
7 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
8 *
9 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 */
26
27 package org.postgis;
28
29 import java.sql.SQLException;
30 import java.util.List;
31
32 public class Point extends Geometry {
33 /* JDK 1.5 Serialization */
34 private static final long serialVersionUID = 0x100;
35
36 public static final boolean CUTINTS = true;
37
38 public int hashCode() {
39 return super.hashCode() ^ hashCode(x) ^ hashCode(y) ^ hashCode(z) ^ hashCode(m);
40 }
41
42 public static int hashCode(double value) {
43 long v = Double.doubleToLongBits(value);
44 return (int) (v ^ (v >>> 32));
45 }
46
47 protected boolean equalsintern(Geometry otherg) {
48 Point other = (Point) otherg;
49 return equals(other);
50 }
51
52 public static boolean double_equals(double a, double b) {
53 if ( Double.isNaN(a) && Double.isNaN(b) ) {
54 return true;
55 }
56 else {
57 return (a == b);
58 }
59 }
60
61 public final boolean equals(Point other) {
62 boolean xequals = double_equals(x, other.x);
63 boolean yequals = double_equals(y, other.y);
64 boolean zequals = ((dimension == 2) || double_equals(z, other.z));
65 boolean mequals = ((haveMeasure == false) || double_equals(m,other.m));
66 boolean result = xequals && yequals && zequals && mequals;
67 return result;
68 }
69
70 public Point getPoint(int index) {
71 if (index == 0) {
72 return this;
73 } else {
74 throw new ArrayIndexOutOfBoundsException("Point only has a single Point! " + index);
75 }
76 }
77
78 /** Optimized versions for this special case */
79 public Point getFirstPoint() {
80 return this;
81 }
82
83 /** Optimized versions for this special case */
84 public Point getLastPoint() {
85 return this;
86 }
87
88 public int numPoints() {
89 return 1;
90 }
91
92 /**
93 * The X coordinate of the point.
94 * In most long/lat systems, this is the longitude.
95 */
96 public double x;
97
98 /**
99 * The Y coordinate of the point.
100 * In most long/lat systems, this is the latitude.
101 */
102 public double y;
103
104 /**
105 * The Z coordinate of the point.
106 * In most long/lat systems, this is a radius from the
107 * center of the earth, or the height / elevation over
108 * the ground.
109 */
110 public double z;
111
112 /**
113 * The measure of the point.
114 */
115 public double m = 0.0;
116
117 public Point() {
118 super(POINT);
119 }
120
121 /** Constructs a new Point
122 * @param x the longitude / x ordinate
123 * @param y the latitude / y ordinate
124 * @param z the radius / height / elevation / z ordinate
125 */
126 public Point(double x, double y, double z) {
127 this();
128 this.x = x;
129 this.y = y;
130 this.z = z;
131 dimension = 3;
132 }
133
134 /** Constructs a new Point
135 * @param x the longitude / x ordinate
136 * @param y the latitude / y ordinate
137 */
138 public Point(double x, double y) {
139 this();
140 this.x = x;
141 this.y = y;
142 this.z = 0.0;
143 dimension = 2;
144 }
145
146 /**
147 * Construct a Point from EWKT.
148 *
149 * (3D and measures are legal, but SRID is not allowed).
150 *
151 * @param value String representation of the geometry.
152 * @throws SQLException when a SQLException occurs
153 */
154 public Point(String value) throws SQLException {
155 this(value, false);
156 }
157
158 /**
159 * Construct a Point
160 *
161 * @param value The text representation of this point
162 * @param haveM Hint whether we have a measure. This is used by other
163 * geometries parsing inner points where we only get "1 2 3 4"
164 * like strings without the "POINT(" and ")" stuff. If there
165 * acutally is a POINTM prefix, this overrides the given value.
166 * However, POINT does not set it to false, as they can be
167 * contained in measured collections, as in
168 * "GEOMETRYCOLLECTIONM(POINT(0 0 0))".
169 * @throws SQLException when a SQLException occurs
170 */
171 protected Point(String value, boolean haveM) throws SQLException {
172 this();
173 value = initSRID(value);
174
175 if (value.indexOf("POINTM") == 0) {
176 haveM = true;
177 value = value.substring(6).trim();
178 } else if (value.indexOf("POINT") == 0) {
179 value = value.substring(5).trim();
180 }
181 String valueNoParans = GeometryTokenizer.removeLeadingAndTrailingStrings(value, "(", ")");
182 List<String> tokens = GeometryTokenizer.tokenize(valueNoParans, ' ');
183 try {
184 x = Double.valueOf(tokens.get(0)).doubleValue();
185 y = Double.valueOf(tokens.get(1)).doubleValue();
186 haveM |= tokens.size() == 4;
187 if ((tokens.size() == 3 && !haveM) || (tokens.size() == 4)) {
188 z = Double.valueOf(tokens.get(2)).doubleValue();
189 dimension = 3;
190 } else {
191 dimension = 2;
192 }
193 if (haveM) {
194 m = Double.valueOf(tokens.get(dimension)).doubleValue();
195 }
196 } catch (NumberFormatException e) {
197 throw new SQLException("Error parsing Point: " + e.toString());
198 }
199 haveMeasure = haveM;
200 }
201
202 public void innerWKT(StringBuffer sb) {
203 sb.append(x);
204 if (CUTINTS)
205 cutint(sb);
206 sb.append(' ');
207 sb.append(y);
208 if (CUTINTS)
209 cutint(sb);
210 if (dimension == 3) {
211 sb.append(' ');
212 sb.append(z);
213 if (CUTINTS)
214 cutint(sb);
215 }
216 if (haveMeasure) {
217 sb.append(' ');
218 sb.append(m);
219 if (CUTINTS)
220 cutint(sb);
221 }
222 }
223
224 private static void cutint(StringBuffer sb) {
225 int l = sb.length() - 2;
226 if ((sb.charAt(l + 1) == '0') && (sb.charAt(l) == '.')) {
227 sb.setLength(l);
228 }
229 }
230
231 public double getX() {
232 return x;
233 }
234
235 public double getY() {
236 return y;
237 }
238
239 public double getZ() {
240 return z;
241 }
242
243 public double getM() {
244 return m;
245 }
246
247 public void setX(double x) {
248 this.x = x;
249 }
250
251 public void setY(double y) {
252 this.y = y;
253 }
254
255 public void setZ(double z) {
256 this.z = z;
257 }
258
259 public void setM(double m) {
260 haveMeasure = true;
261 this.m = m;
262 }
263
264 public void setX(int x) {
265 this.x = x;
266 }
267
268 public void setY(int y) {
269 this.y = y;
270 }
271
272 public void setZ(int z) {
273 this.z = z;
274 }
275
276 public double distance(Point other) {
277 double tx, ty, tz;
278 if (this.dimension != other.dimension) {
279 throw new IllegalArgumentException("Points have different dimensions!");
280 }
281 tx = this.x - other.x;
282 switch (this.dimension) {
283 case 1 :
284 return Math.sqrt(tx * tx);
285 case 2 :
286 ty = this.y - other.y;
287 return Math.sqrt(tx * tx + ty * ty);
288 case 3 :
289 ty = this.y - other.y;
290 tz = this.z - other.z;
291 return Math.sqrt(tx * tx + ty * ty + tz * tz);
292 default :
293 throw new IllegalArgumentException("Illegal dimension of Point" + this.dimension);
294 }
295 }
296
297 public boolean checkConsistency() {
298 return super.checkConsistency() && (this.dimension == 3 || this.z == 0.0)
299 && (this.haveMeasure || this.m == 0.0);
300 }
301 }
+0
-101
postgis-geometry/src/main/java/org/postgis/PointComposedGeom.java less more
0 /*
1 * PointComposedGeom.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - geometry model
4 *
5 * (C) 2004 Paul Ramsey, pramsey@refractions.net
6 *
7 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
8 *
9 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 */
26 package org.postgis;
27
28 import java.sql.SQLException;
29
30 /**
31 * PointComposedGeom - base class for all composed geoms that contain only
32 * points.
33 *
34 * @author markus.schaber@logix-tt.com
35 *
36 */
37
38 public abstract class PointComposedGeom extends ComposedGeom {
39 /* JDK 1.5 Serialization */
40 private static final long serialVersionUID = 0x100;
41
42 protected PointComposedGeom(int type) {
43 super(type);
44 }
45
46 protected PointComposedGeom(int type, Point[] points) {
47 super(type, points);
48 }
49
50 public PointComposedGeom(int type, String value) throws SQLException {
51 this(type, value, false);
52 }
53
54 public PointComposedGeom(int type, String value, boolean haveM) throws SQLException {
55 super(type, value, haveM);
56 }
57
58 protected Geometry createSubGeomInstance(String token, boolean haveM) throws SQLException {
59 return new Point(token, haveM);
60 }
61
62 protected Geometry[] createSubGeomArray(int pointcount) {
63 return new Point[pointcount];
64 }
65
66 protected void innerWKT(StringBuffer sb) {
67 subgeoms[0].innerWKT(sb);
68 for (int i = 1; i < subgeoms.length; i++) {
69 sb.append(',');
70 subgeoms[i].innerWKT(sb);
71 }
72 }
73
74 /**
75 * optimized version
76 */
77 public int numPoints() {
78 return subgeoms.length;
79 }
80
81 /**
82 * optimized version
83 */
84 public Point getPoint(int idx) {
85 if (idx >= 0 & idx < subgeoms.length) {
86 return (Point) subgeoms[idx];
87 } else {
88 return null;
89 }
90 }
91
92 /**
93 * Get the underlying Point array
94 *
95 * @return an array of Points within this geometry
96 */
97 public Point[] getPoints() {
98 return (Point[]) subgeoms;
99 }
100 }
+0
-71
postgis-geometry/src/main/java/org/postgis/Polygon.java less more
0 /*
1 * Polygon.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - geometry model
4 *
5 * (C) 2004 Paul Ramsey, pramsey@refractions.net
6 *
7 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
8 *
9 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 */
26
27 package org.postgis;
28
29 import java.sql.SQLException;
30
31 public class Polygon extends ComposedGeom {
32 /* JDK 1.5 Serialization */
33 private static final long serialVersionUID = 0x100;
34
35 public Polygon() {
36 super(POLYGON);
37 }
38
39 public Polygon(LinearRing[] rings) {
40 super(POLYGON, rings);
41 }
42
43 public Polygon(String value) throws SQLException {
44 this(value, false);
45 }
46
47 public Polygon(String value, boolean haveM) throws SQLException {
48 super(POLYGON, value, haveM);
49 }
50
51 protected Geometry createSubGeomInstance(String token, boolean haveM) throws SQLException {
52 return new LinearRing(token, haveM);
53 }
54
55 protected Geometry[] createSubGeomArray(int ringcount) {
56 return new LinearRing[ringcount];
57 }
58
59 public int numRings() {
60 return subgeoms.length;
61 }
62
63 public LinearRing getRing(int idx) {
64 if (idx >= 0 & idx < subgeoms.length) {
65 return (LinearRing) subgeoms[idx];
66 } else {
67 return null;
68 }
69 }
70 }
+0
-246
postgis-geometry/src/main/java/org/postgis/binary/BinaryParser.java less more
0 /*
1 * BinaryParser.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - Binary Parser
4 *
5 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
6 *
7 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24 package org.postgis.binary;
25
26 import org.postgis.Geometry;
27 import org.postgis.GeometryCollection;
28 import org.postgis.LineString;
29 import org.postgis.LinearRing;
30 import org.postgis.MultiLineString;
31 import org.postgis.MultiPoint;
32 import org.postgis.MultiPolygon;
33 import org.postgis.Point;
34 import org.postgis.Polygon;
35 import org.postgis.binary.ByteGetter.BinaryByteGetter;
36 import org.postgis.binary.ByteGetter.StringByteGetter;
37
38
39 /**
40 * Parse binary representation of geometries.
41 *
42 * It should be easy to add char[] and CharSequence ByteGetter instances,
43 * although the latter one is not compatible with older jdks.
44 *
45 * I did not implement real unsigned 32-bit integers or emulate them with long,
46 * as both java Arrays and Strings currently can have only 2^31-1 elements
47 * (bytes), so we cannot even get or build Geometries with more than approx.
48 * 2^28 coordinates (8 bytes each).
49 *
50 * @author {@literal Markus Schaber <markus.schaber@logix-tt.com>}
51 *
52 */
53 public class BinaryParser {
54
55 /**
56 * Get the appropriate ValueGetter for my endianness
57 *
58 * @param bytes The appropriate Byte Getter
59 *
60 * @return the ValueGetter
61 */
62 public static ValueGetter valueGetterForEndian(ByteGetter bytes) {
63 if (bytes.get(0) == ValueGetter.XDR.NUMBER) { // XDR
64 return new ValueGetter.XDR(bytes);
65 } else if (bytes.get(0) == ValueGetter.NDR.NUMBER) {
66 return new ValueGetter.NDR(bytes);
67 } else {
68 throw new IllegalArgumentException("Unknown Endian type:" + bytes.get(0));
69 }
70 }
71
72 /**
73 * Parse a hex encoded geometry
74 *
75 * Is synchronized to protect offset counter. (Unfortunately, Java does not
76 * have neither call by reference nor multiple return values.)
77 *
78 * @param value String containing the data to be parsed
79 * @return resulting geometry for the parsed data
80 */
81 public synchronized Geometry parse(String value) {
82 StringByteGetter bytes = new StringByteGetter(value);
83 return parseGeometry(valueGetterForEndian(bytes));
84 }
85
86 /**
87 * Parse a binary encoded geometry.
88 *
89 * Is synchronized to protect offset counter. (Unfortunately, Java does not
90 * have neither call by reference nor multiple return values.)
91 *
92 * @param value byte array containing the data to be parsed
93 * @return resulting geometry for the parsed data
94 */
95 public synchronized Geometry parse(byte[] value) {
96 BinaryByteGetter bytes = new BinaryByteGetter(value);
97 return parseGeometry(valueGetterForEndian(bytes));
98 }
99
100 /**
101 * Parse a geometry starting at offset.
102 *
103 * @param data ValueGetter with the data to be parsed
104 * @return the parsed geometry
105 * */
106 protected Geometry parseGeometry(ValueGetter data) {
107 byte endian = data.getByte(); // skip and test endian flag
108 if (endian != data.endian) {
109 throw new IllegalArgumentException("Endian inconsistency!");
110 }
111 int typeword = data.getInt();
112
113 int realtype = typeword & 0x1FFFFFFF; // cut off high flag bits
114
115 boolean haveZ = (typeword & 0x80000000) != 0;
116 boolean haveM = (typeword & 0x40000000) != 0;
117 boolean haveS = (typeword & 0x20000000) != 0;
118
119 int srid = Geometry.UNKNOWN_SRID;
120
121 if (haveS) {
122 srid = Geometry.parseSRID(data.getInt());
123 }
124 Geometry result1;
125 switch (realtype) {
126 case Geometry.POINT :
127 result1 = parsePoint(data, haveZ, haveM);
128 break;
129 case Geometry.LINESTRING :
130 result1 = parseLineString(data, haveZ, haveM);
131 break;
132 case Geometry.POLYGON :
133 result1 = parsePolygon(data, haveZ, haveM);
134 break;
135 case Geometry.MULTIPOINT :
136 result1 = parseMultiPoint(data);
137 break;
138 case Geometry.MULTILINESTRING :
139 result1 = parseMultiLineString(data);
140 break;
141 case Geometry.MULTIPOLYGON :
142 result1 = parseMultiPolygon(data);
143 break;
144 case Geometry.GEOMETRYCOLLECTION :
145 result1 = parseCollection(data);
146 break;
147 default :
148 throw new IllegalArgumentException("Unknown Geometry Type: " + realtype);
149 }
150
151 Geometry result = result1;
152
153 if (srid != Geometry.UNKNOWN_SRID) {
154 result.setSrid(srid);
155 }
156 return result;
157 }
158
159 private Point parsePoint(ValueGetter data, boolean haveZ, boolean haveM) {
160 double X = data.getDouble();
161 double Y = data.getDouble();
162 Point result;
163 if (haveZ) {
164 double Z = data.getDouble();
165 result = new Point(X, Y, Z);
166 } else {
167 result = new Point(X, Y);
168 }
169
170 if (haveM) {
171 result.setM(data.getDouble());
172 }
173
174 return result;
175 }
176
177 /** Parse an Array of "full" Geometries */
178 private void parseGeometryArray(ValueGetter data, Geometry[] container) {
179 for (int i = 0; i < container.length; i++) {
180 container[i] = parseGeometry(data);
181 }
182 }
183
184 /**
185 * Parse an Array of "slim" Points (without endianness and type, part of
186 * LinearRing and Linestring, but not MultiPoint!
187 *
188 * @param haveZ
189 * @param haveM
190 */
191 private Point[] parsePointArray(ValueGetter data, boolean haveZ, boolean haveM) {
192 int count = data.getInt();
193 Point[] result = new Point[count];
194 for (int i = 0; i < count; i++) {
195 result[i] = parsePoint(data, haveZ, haveM);
196 }
197 return result;
198 }
199
200 private MultiPoint parseMultiPoint(ValueGetter data) {
201 Point[] points = new Point[data.getInt()];
202 parseGeometryArray(data, points);
203 return new MultiPoint(points);
204 }
205
206 private LineString parseLineString(ValueGetter data, boolean haveZ, boolean haveM) {
207 Point[] points = parsePointArray(data, haveZ, haveM);
208 return new LineString(points);
209 }
210
211 private LinearRing parseLinearRing(ValueGetter data, boolean haveZ, boolean haveM) {
212 Point[] points = parsePointArray(data, haveZ, haveM);
213 return new LinearRing(points);
214 }
215
216 private Polygon parsePolygon(ValueGetter data, boolean haveZ, boolean haveM) {
217 int count = data.getInt();
218 LinearRing[] rings = new LinearRing[count];
219 for (int i = 0; i < count; i++) {
220 rings[i] = parseLinearRing(data, haveZ, haveM);
221 }
222 return new Polygon(rings);
223 }
224
225 private MultiLineString parseMultiLineString(ValueGetter data) {
226 int count = data.getInt();
227 LineString[] strings = new LineString[count];
228 parseGeometryArray(data, strings);
229 return new MultiLineString(strings);
230 }
231
232 private MultiPolygon parseMultiPolygon(ValueGetter data) {
233 int count = data.getInt();
234 Polygon[] polys = new Polygon[count];
235 parseGeometryArray(data, polys);
236 return new MultiPolygon(polys);
237 }
238
239 private GeometryCollection parseCollection(ValueGetter data) {
240 int count = data.getInt();
241 Geometry[] geoms = new Geometry[count];
242 parseGeometryArray(data, geoms);
243 return new GeometryCollection(geoms);
244 }
245 }
+0
-377
postgis-geometry/src/main/java/org/postgis/binary/BinaryWriter.java less more
0 /*
1 * BinaryWriter.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - Binary Writer
4 *
5 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
6 *
7 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24 package org.postgis.binary;
25
26 import org.postgis.Geometry;
27 import org.postgis.GeometryCollection;
28 import org.postgis.LineString;
29 import org.postgis.LinearRing;
30 import org.postgis.MultiLineString;
31 import org.postgis.MultiPoint;
32 import org.postgis.MultiPolygon;
33 import org.postgis.Point;
34 import org.postgis.Polygon;
35
36
37 /**
38 * Create binary representation of geometries. Currently, only text rep (hexed)
39 * implementation is tested.
40 *
41 * It should be easy to add char[] and CharSequence ByteGetter instances,
42 * although the latter one is not compatible with older jdks.
43 *
44 * I did not implement real unsigned 32-bit integers or emulate them with long,
45 * as both java Arrays and Strings currently can have only 2^31-1 elements
46 * (bytes), so we cannot even get or build Geometries with more than approx.
47 * 2^28 coordinates (8 bytes each).
48 *
49 * @author markus.schaber@logi-track.com
50 *
51 */
52 public class BinaryWriter {
53
54 /**
55 * Get the appropriate ValueGetter for my endianness
56 *
57 * @param bytes The ByteSetter to use
58 * @param endian the endian for the ValueSetter to use
59 * @return the ValueGetter
60 */
61 public static ValueSetter valueSetterForEndian(ByteSetter bytes, byte endian) {
62 if (endian == ValueSetter.XDR.NUMBER) { // XDR
63 return new ValueSetter.XDR(bytes);
64 } else if (endian == ValueSetter.NDR.NUMBER) {
65 return new ValueSetter.NDR(bytes);
66 } else {
67 throw new IllegalArgumentException("Unknown Endian type:" + endian);
68 }
69 }
70
71 /**
72 * Write a hex encoded geometry
73 *
74 * Is synchronized to protect offset counter. (Unfortunately, Java does not
75 * have neither call by reference nor multiple return values.) This is a
76 * TODO item.
77 *
78 * The geometry you put in must be consistent, geom.checkConsistency() must
79 * return true. If not, the result may be invalid WKB.
80 *
81 * @see Geometry#checkConsistency() the consistency checker
82 *
83 * @param geom the geometry to be written
84 * @param REP endianness to write the bytes with
85 * @return String containing the hex encoded geometry
86 */
87 public synchronized String writeHexed(Geometry geom, byte REP) {
88 int length = estimateBytes(geom);
89 ByteSetter.StringByteSetter bytes = new ByteSetter.StringByteSetter(length);
90 writeGeometry(geom, valueSetterForEndian(bytes, REP));
91 return bytes.result();
92 }
93
94 public synchronized String writeHexed(Geometry geom) {
95 return writeHexed(geom, ValueSetter.NDR.NUMBER);
96 }
97
98 /**
99 * Write a binary encoded geometry.
100 *
101 * Is synchronized to protect offset counter. (Unfortunately, Java does not
102 * have neither call by reference nor multiple return values.) This is a
103 * TODO item.
104 *
105 * The geometry you put in must be consistent, geom.checkConsistency() must
106 * return true. If not, the result may be invalid WKB.
107 *
108 * @see Geometry#checkConsistency()
109 *
110 * @param geom the geometry to be written
111 * @param REP endianness to write the bytes with
112 * @return byte array containing the encoded geometry
113 */
114 public synchronized byte[] writeBinary(Geometry geom, byte REP) {
115 int length = estimateBytes(geom);
116 ByteSetter.BinaryByteSetter bytes = new ByteSetter.BinaryByteSetter(length);
117 writeGeometry(geom, valueSetterForEndian(bytes, REP));
118 return bytes.result();
119 }
120
121 public synchronized byte[] writeBinary(Geometry geom) {
122 return writeBinary(geom, ValueSetter.NDR.NUMBER);
123 }
124
125 /**
126 * Parse a geometry starting at offset.
127 * @param geom the geometry to write
128 * @param dest the value setting to be used for writing
129 */
130 protected void writeGeometry(Geometry geom, ValueSetter dest) {
131 // write endian flag
132 dest.setByte(dest.endian);
133
134 // write typeword
135 int typeword = geom.type;
136 if (geom.dimension == 3) {
137 typeword |= 0x80000000;
138 }
139 if (geom.haveMeasure) {
140 typeword |= 0x40000000;
141 }
142 if (geom.srid != Geometry.UNKNOWN_SRID) {
143 typeword |= 0x20000000;
144 }
145
146 dest.setInt(typeword);
147
148 if (geom.srid != Geometry.UNKNOWN_SRID) {
149 dest.setInt(geom.srid);
150 }
151
152 switch (geom.type) {
153 case Geometry.POINT :
154 writePoint((Point) geom, dest);
155 break;
156 case Geometry.LINESTRING :
157 writeLineString((LineString) geom, dest);
158 break;
159 case Geometry.POLYGON :
160 writePolygon((Polygon) geom, dest);
161 break;
162 case Geometry.MULTIPOINT :
163 writeMultiPoint((MultiPoint) geom, dest);
164 break;
165 case Geometry.MULTILINESTRING :
166 writeMultiLineString((MultiLineString) geom, dest);
167 break;
168 case Geometry.MULTIPOLYGON :
169 writeMultiPolygon((MultiPolygon) geom, dest);
170 break;
171 case Geometry.GEOMETRYCOLLECTION :
172 writeCollection((GeometryCollection) geom, dest);
173 break;
174 default :
175 throw new IllegalArgumentException("Unknown Geometry Type: " + geom.type);
176 }
177 }
178
179 /**
180 * Writes a "slim" Point (without endiannes, srid ant type, only the
181 * ordinates and measure. Used by writeGeometry as ell as writePointArray.
182 */
183 private void writePoint(Point geom, ValueSetter dest) {
184 dest.setDouble(geom.x);
185 dest.setDouble(geom.y);
186
187 if (geom.dimension == 3) {
188 dest.setDouble(geom.z);
189 }
190
191 if (geom.haveMeasure) {
192 dest.setDouble(geom.m);
193 }
194 }
195
196 /** Write an Array of "full" Geometries */
197 private void writeGeometryArray(Geometry[] container, ValueSetter dest) {
198 for (int i = 0; i < container.length; i++) {
199 writeGeometry(container[i], dest);
200 }
201 }
202
203 /**
204 * Write an Array of "slim" Points (without endianness, srid and type, part
205 * of LinearRing and Linestring, but not MultiPoint!
206 */
207 private void writePointArray(Point[] geom, ValueSetter dest) {
208 // number of points
209 dest.setInt(geom.length);
210 for (int i = 0; i < geom.length; i++) {
211 writePoint(geom[i], dest);
212 }
213 }
214
215 private void writeMultiPoint(MultiPoint geom, ValueSetter dest) {
216 dest.setInt(geom.numPoints());
217 writeGeometryArray(geom.getPoints(), dest);
218 }
219
220 private void writeLineString(LineString geom, ValueSetter dest) {
221 writePointArray(geom.getPoints(), dest);
222 }
223
224 private void writeLinearRing(LinearRing geom, ValueSetter dest) {
225 writePointArray(geom.getPoints(), dest);
226 }
227
228 private void writePolygon(Polygon geom, ValueSetter dest) {
229 dest.setInt(geom.numRings());
230 for (int i = 0; i < geom.numRings(); i++) {
231 writeLinearRing(geom.getRing(i), dest);
232 }
233 }
234
235 private void writeMultiLineString(MultiLineString geom, ValueSetter dest) {
236 dest.setInt(geom.numLines());
237 writeGeometryArray(geom.getLines(), dest);
238 }
239
240 private void writeMultiPolygon(MultiPolygon geom, ValueSetter dest) {
241 dest.setInt(geom.numPolygons());
242 writeGeometryArray(geom.getPolygons(), dest);
243 }
244
245 private void writeCollection(GeometryCollection geom, ValueSetter dest) {
246 dest.setInt(geom.numGeoms());
247 writeGeometryArray(geom.getGeometries(), dest);
248 }
249
250 /**
251 * Estimate how much bytes a geometry will need in WKB.
252 *
253 * @param geom Geometry to estimate.
254 * @return estimated number of bytes
255 */
256 protected int estimateBytes(Geometry geom) {
257 int result = 0;
258
259 // write endian flag
260 result += 1;
261
262 // write typeword
263 result += 4;
264
265 if (geom.srid != Geometry.UNKNOWN_SRID) {
266 result += 4;
267 }
268
269 switch (geom.type) {
270 case Geometry.POINT :
271 result += estimatePoint((Point) geom);
272 break;
273 case Geometry.LINESTRING :
274 result += estimateLineString((LineString) geom);
275 break;
276 case Geometry.POLYGON :
277 result += estimatePolygon((Polygon) geom);
278 break;
279 case Geometry.MULTIPOINT :
280 result += estimateMultiPoint((MultiPoint) geom);
281 break;
282 case Geometry.MULTILINESTRING :
283 result += estimateMultiLineString((MultiLineString) geom);
284 break;
285 case Geometry.MULTIPOLYGON :
286 result += estimateMultiPolygon((MultiPolygon) geom);
287 break;
288 case Geometry.GEOMETRYCOLLECTION :
289 result += estimateCollection((GeometryCollection) geom);
290 break;
291 default :
292 throw new IllegalArgumentException("Unknown Geometry Type: " + geom.type);
293 }
294 return result;
295 }
296
297 private int estimatePoint(Point geom) {
298 // x, y both have 8 bytes
299 int result = 16;
300 if (geom.dimension == 3) {
301 result += 8;
302 }
303
304 if (geom.haveMeasure) {
305 result += 8;
306 }
307 return result;
308 }
309
310 /** Write an Array of "full" Geometries */
311 private int estimateGeometryArray(Geometry[] container) {
312 int result = 0;
313 for (int i = 0; i < container.length; i++) {
314 result += estimateBytes(container[i]);
315 }
316 return result;
317 }
318
319 /**
320 * Write an Array of "slim" Points (without endianness and type, part of
321 * LinearRing and Linestring, but not MultiPoint!
322 */
323 private int estimatePointArray(Point[] geom) {
324 // number of points
325 int result = 4;
326
327 // And the amount of the points itsself, in consistent geometries
328 // all points have equal size.
329 if (geom.length > 0) {
330 result += geom.length * estimatePoint(geom[0]);
331 }
332 return result;
333 }
334
335 private int estimateMultiPoint(MultiPoint geom) {
336 // int size
337 int result = 4;
338 if (geom.numPoints() > 0) {
339 // We can shortcut here, as all subgeoms have the same fixed size
340 result += geom.numPoints() * estimateBytes(geom.getFirstPoint());
341 }
342 return result;
343 }
344
345 private int estimateLineString(LineString geom) {
346 return estimatePointArray(geom.getPoints());
347 }
348
349 private int estimateLinearRing(LinearRing geom) {
350 return estimatePointArray(geom.getPoints());
351 }
352
353 private int estimatePolygon(Polygon geom) {
354 // int length
355 int result = 4;
356 for (int i = 0; i < geom.numRings(); i++) {
357 result += estimateLinearRing(geom.getRing(i));
358 }
359 return result;
360 }
361
362 private int estimateMultiLineString(MultiLineString geom) {
363 // 4-byte count + subgeometries
364 return 4 + estimateGeometryArray(geom.getLines());
365 }
366
367 private int estimateMultiPolygon(MultiPolygon geom) {
368 // 4-byte count + subgeometries
369 return 4 + estimateGeometryArray(geom.getPolygons());
370 }
371
372 private int estimateCollection(GeometryCollection geom) {
373 // 4-byte count + subgeometries
374 return 4 + estimateGeometryArray(geom.getGeometries());
375 }
376 }
+0
-76
postgis-geometry/src/main/java/org/postgis/binary/ByteGetter.java less more
0 /*
1 * ByteGetter.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - Binary Parser
4 *
5 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
6 *
7 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24
25 package org.postgis.binary;
26
27 public abstract class ByteGetter {
28 /**
29 * Get a byte.
30 *
31 * @param index the index to get the value from
32 * @return The result is returned as Int to eliminate sign problems when
33 * or'ing several values together.
34 */
35 public abstract int get(int index);
36
37 public static class BinaryByteGetter extends ByteGetter {
38 private byte[] array;
39
40 public BinaryByteGetter(byte[] array) {
41 this.array = array;
42 }
43
44 public int get(int index) {
45 return array[index] & 0xFF; // mask out sign-extended bits.
46 }
47 }
48
49 public static class StringByteGetter extends ByteGetter {
50 private String rep;
51
52 public StringByteGetter(String rep) {
53 this.rep = rep;
54 }
55
56 public int get(int index) {
57 index *= 2;
58 int high = unhex(rep.charAt(index));
59 int low = unhex(rep.charAt(index + 1));
60 return (high << 4) + low;
61 }
62
63 public static byte unhex(char c) {
64 if (c >= '0' && c <= '9') {
65 return (byte) (c - '0');
66 } else if (c >= 'A' && c <= 'F') {
67 return (byte) (c - 'A' + 10);
68 } else if (c >= 'a' && c <= 'f') {
69 return (byte) (c - 'a' + 10);
70 } else {
71 throw new IllegalArgumentException("No valid Hex char " + c);
72 }
73 }
74 }
75 }
+0
-88
postgis-geometry/src/main/java/org/postgis/binary/ByteSetter.java less more
0 /*
1 * ByteSetter.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - Binary Parser
4 *
5 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
6 *
7 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24
25 package org.postgis.binary;
26
27 public abstract class ByteSetter {
28
29 /**
30 * Set a byte.
31 *
32 * @param b byte value to set with
33 * @param index index to set
34 */
35 public abstract void set(byte b, int index);
36
37 public static class BinaryByteSetter extends ByteSetter {
38 private byte[] array;
39
40 public BinaryByteSetter(int length) {
41 this.array = new byte[length];
42 }
43
44 public void set(byte b, int index) {
45 array[index] = b; // mask out sign-extended bits.
46 }
47
48 public byte[] result() {
49 return array;
50 }
51
52 public String toString() {
53 char[] arr = new char[array.length];
54 for (int i=0; i<array.length; i++) {
55 arr[i] = (char)(array[i]&0xFF);
56 }
57 return new String(arr);
58 }
59 }
60
61 public static class StringByteSetter extends ByteSetter {
62 protected static final char[] hextypes = "0123456789ABCDEF".toCharArray();
63 private char[] rep;
64
65 public StringByteSetter(int length) {
66 this.rep = new char[length * 2];
67 }
68
69 public void set(byte b, int index) {
70 index *= 2;
71 rep[index] = hextypes[(b >>> 4) & 0xF];
72 rep[index + 1] = hextypes[b & 0xF];
73 }
74
75 public char[] resultAsArray() {
76 return rep;
77 }
78
79 public String result() {
80 return new String(rep);
81 }
82
83 public String toString() {
84 return new String(rep);
85 }
86 }
87 }
+0
-125
postgis-geometry/src/main/java/org/postgis/binary/ValueGetter.java less more
0 /*
1 * ValueGetter.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - Binary Parser
4 *
5 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
6 *
7 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24
25 package org.postgis.binary;
26
27 public abstract class ValueGetter {
28 ByteGetter data;
29 int position;
30 public final byte endian;
31
32 public ValueGetter(ByteGetter data, byte endian) {
33 this.data = data;
34 this.endian = endian;
35 }
36
37 /**
38 * Get a byte, should be equal for all endians
39 *
40 * @return the byte value
41 */
42 public byte getByte() {
43 return (byte) data.get(position++);
44 }
45
46 public int getInt() {
47 int res = getInt(position);
48 position += 4;
49 return res;
50 }
51
52 public long getLong() {
53 long res = getLong(position);
54 position += 8;
55 return res;
56 }
57
58 /**
59 * Get a 32-Bit integer
60 *
61 * @param index the index to get the value from
62 * @return the int value
63 */
64 protected abstract int getInt(int index);
65
66 /**
67 * Get a long value. This is not needed directly, but as a nice side-effect
68 * from GetDouble.
69 *
70 * @param index the index to get the value from
71 * @return the long value
72 */
73 protected abstract long getLong(int index);
74
75 /**
76 * Get a double.
77 *
78 * @return the double value
79 */
80 public double getDouble() {
81 long bitrep = getLong();
82 return Double.longBitsToDouble(bitrep);
83 }
84
85 public static class XDR extends ValueGetter {
86 public static final byte NUMBER = 0;
87
88 public XDR(ByteGetter data) {
89 super(data, NUMBER);
90 }
91
92 protected int getInt(int index) {
93 return (data.get(index) << 24) + (data.get(index + 1) << 16)
94 + (data.get(index + 2) << 8) + data.get(index + 3);
95 }
96
97 protected long getLong(int index) {
98 return ((long) data.get(index) << 56) + ((long) data.get(index + 1) << 48)
99 + ((long) data.get(index + 2) << 40) + ((long) data.get(index + 3) << 32)
100 + ((long) data.get(index + 4) << 24) + ((long) data.get(index + 5) << 16)
101 + ((long) data.get(index + 6) << 8) + ((long) data.get(index + 7) << 0);
102 }
103 }
104
105 public static class NDR extends ValueGetter {
106 public static final byte NUMBER = 1;
107
108 public NDR(ByteGetter data) {
109 super(data, NUMBER);
110 }
111
112 protected int getInt(int index) {
113 return (data.get(index + 3) << 24) + (data.get(index + 2) << 16)
114 + (data.get(index + 1) << 8) + data.get(index);
115 }
116
117 protected long getLong(int index) {
118 return ((long) data.get(index + 7) << 56) + ((long) data.get(index + 6) << 48)
119 + ((long) data.get(index + 5) << 40) + ((long) data.get(index + 4) << 32)
120 + ((long) data.get(index + 3) << 24) + ((long) data.get(index + 2) << 16)
121 + ((long) data.get(index + 1) << 8) + ((long) data.get(index) << 0);
122 }
123 }
124 }
+0
-144
postgis-geometry/src/main/java/org/postgis/binary/ValueSetter.java less more
0 /*
1 * ValueSetter.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - Binary Parser
4 *
5 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
6 *
7 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24
25 package org.postgis.binary;
26
27 public abstract class ValueSetter {
28 ByteSetter data;
29 int position=0;
30 public final byte endian;
31
32 public ValueSetter(ByteSetter data, byte endian) {
33 this.data = data;
34 this.endian = endian;
35 }
36
37 /**
38 * Set a byte, should be equal for all endians
39 *
40 * @param value byte value to be set with.
41 */
42 public void setByte(byte value) {
43 data.set(value, position);
44 position += 1;
45 }
46
47 public void setInt(int value) {
48 setInt(value, position);
49 position += 4;
50 }
51
52 public void setLong(long value) {
53 setLong(value, position);
54 position += 8;
55 }
56
57 /**
58 * Set a 32-Bit integer
59 *
60 * @param value int value to be set with
61 * @param index int value for the index
62 *
63 */
64 protected abstract void setInt(int value, int index);
65
66 /**
67 * Set a long value. This is not needed directly, but as a nice side-effect
68 * from GetDouble.
69 *
70 * @param data int value to be set with
71 * @param index int value for the index
72 */
73 protected abstract void setLong(long data, int index);
74
75 /**
76 * Set a double.
77 *
78 * @param data double value to be set with
79 */
80 public void setDouble(double data) {
81 long bitrep = Double.doubleToLongBits(data);
82 setLong(bitrep);
83 }
84
85 public String toString() {
86 String name = getClass().getName();
87 int pointpos = name.lastIndexOf('.');
88 String klsName = name.substring(pointpos+1);
89 return klsName+"('"+(data==null?"NULL":data.toString()+"')");
90 }
91
92 public static class XDR extends ValueSetter {
93 public static final byte NUMBER = 0;
94
95 public XDR(ByteSetter data) {
96 super(data, NUMBER);
97 }
98
99 protected void setInt(int value, int index) {
100 data.set((byte) (value >>> 24), index);
101 data.set((byte) (value >>> 16), index + 1);
102 data.set((byte) (value >>> 8), index + 2);
103 data.set((byte) value, index + 3);
104 }
105
106 protected void setLong(long value, int index) {
107 data.set((byte) (value >>> 56), index);
108 data.set((byte) (value >>> 48), index + 1);
109 data.set((byte) (value >>> 40), index + 2);
110 data.set((byte) (value >>> 32), index + 3);
111 data.set((byte) (value >>> 24), index + 4);
112 data.set((byte) (value >>> 16), index + 5);
113 data.set((byte) (value >>> 8), index + 6);
114 data.set((byte) value, index + 7);
115 }
116 }
117
118 public static class NDR extends ValueSetter {
119 public static final byte NUMBER = 1;
120
121 public NDR(ByteSetter data) {
122 super(data, NUMBER);
123 }
124
125 protected void setInt(int value, int index) {
126 data.set((byte) (value >>> 24), index + 3);
127 data.set((byte) (value >>> 16), index + 2);
128 data.set((byte) (value >>> 8), index + 1);
129 data.set((byte) value, index);
130 }
131
132 protected void setLong(long value, int index) {
133 data.set((byte) (value >>> 56), index + 7);
134 data.set((byte) (value >>> 48), index + 6);
135 data.set((byte) (value >>> 40), index + 5);
136 data.set((byte) (value >>> 32), index + 4);
137 data.set((byte) (value >>> 24), index + 3);
138 data.set((byte) (value >>> 16), index + 2);
139 data.set((byte) (value >>> 8), index + 1);
140 data.set((byte) value, index);
141 }
142 }
143 }
+0
-71
postgis-geometry/src/main/java/org/postgis/util/VersionFunctions.java less more
0 /*
1 * This library is free software; you can redistribute it and/or
2 * modify it under the terms of the GNU Lesser General Public
3 * License as published by the Free Software Foundation; either
4 * version 2.1 of the License, or (at your option) any later version.
5 *
6 * This library is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 * Lesser General Public License for more details.
10 *
11 * You should have received a copy of the GNU Lesser General Public
12 * License along with this library; if not, write to the Free Software
13 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
14 *
15 * (C) 2020 Phillip Ross, phillip.w.g.ross@gmail.com
16 */
17
18 package org.postgis.util;
19
20
21 /**
22 * An enumeration of existing version functions.
23 *
24 * @author Phillip Ross
25 */
26 public enum VersionFunctions {
27
28 /** The function to return the full version and build configuration info of the PostGIS Server. */
29 POSTGIS_FULL_VERSION,
30
31 /** The function to return the version of the GDAL library. */
32 POSTGIS_GDAL_VERSION,
33
34 /** The function to return the version of the GEOS library. */
35 POSTGIS_GEOS_VERSION,
36
37 /** The function to return the build date of the PostGIS library. */
38 POSTGIS_LIB_BUILD_DATE,
39
40 /** The function to return the version of the PostGIS library. */
41 POSTGIS_LIB_VERSION,
42
43 /** The function to return the version of the libjson library. */
44 POSTGIS_LIBJSON_VERSION,
45
46 /** The function to return the version of the libxml library. */
47 POSTGIS_LIBXML_VERSION,
48
49 /** The function to return the version of the Proj library. */
50 POSTGIS_PROJ_VERSION,
51
52 /** The function to return the version of the raster library. */
53 POSTGIS_RASTER_LIB_VERSION,
54
55 /** The function to return the build date of the scripts. */
56 POSTGIS_SCRIPTS_BUILD_DATE,
57
58 /** The function to return the version of the scripts installed in the database. */
59 POSTGIS_SCRIPTS_INSTALLED,
60
61 /** The function to return the version of the scripts released with the installed PostGIS library. */
62 POSTGIS_SCRIPTS_RELEASED,
63
64 /** The function to return the Subversion version of the PostGIS Server. */
65 POSTGIS_SVN_VERSION,
66
67 /** The function to return the version of the PostGIS Server. */
68 POSTGIS_VERSION
69
70 }
+0
-173
postgis-geometry/src/main/java/org/postgis/util/VersionUtil.java less more
0 /*
1 * This library is free software; you can redistribute it and/or
2 * modify it under the terms of the GNU Lesser General Public
3 * License as published by the Free Software Foundation; either
4 * version 2.1 of the License, or (at your option) any later version.
5 *
6 * This library is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 * Lesser General Public License for more details.
10 *
11 * You should have received a copy of the GNU Lesser General Public
12 * License along with this library; if not, write to the Free Software
13 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
14 *
15 * (C) 2020 Phillip Ross, phillip.w.g.ross@gmail.com
16 */
17
18 package org.postgis.util;
19
20
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
23
24 import java.sql.Connection;
25 import java.sql.PreparedStatement;
26 import java.sql.ResultSet;
27 import java.sql.SQLException;
28 import java.util.Objects;
29
30
31 /**
32 * Utility for working with PostGIS Server version.
33 *
34 * @author Phillip Ross
35 */
36 public class VersionUtil {
37
38 /** The static logger instance. */
39 private static final Logger logger = LoggerFactory.getLogger(VersionUtil.class);
40
41 /** The string to match when determining a function does not exist from the content of an error message. */
42 public static final String NONEXISTENT_FUNCTION_ERROR_MESSAGE_CONTENT = "does not exist";
43
44 /** The token which separates version components within the PostGIS Server version. */
45 public static final String POSTGIS_SERVER_VERSION_SEPERATOR = ".";
46
47 /** The number of seconds to wait for a connection validation operation. */
48 private static final int DEFAULT_CONNECTION_TIMEOUT = 60;
49
50
51 /**
52 * Query a specific version string from the datasource for a specified function.
53 *
54 * @param connection The connection to issue the version query function against.
55 * @param function The version function to use for querying the version.
56 * @return a string version for the specified function.
57 * @throws SQLException when a jdbc exception occurs.
58 */
59 public static String getVersionString(final Connection connection, final String function) throws SQLException {
60 Objects.requireNonNull(connection, "Unable to retrieve version string from a null connection");
61 Objects.requireNonNull(function, "Unable to retrieve version string for a null function");
62 validateConnection(connection);
63
64 String result = "-- unavailable -- ";
65 try (
66 PreparedStatement statement = connection.prepareStatement("SELECT " + function + "()");
67 ResultSet resultSet = statement.executeQuery();
68 ) {
69 if (resultSet.next()) {
70 String version = resultSet.getString(1);
71 if (version != null) {
72 result = version.trim();
73 } else {
74 result = "-- null result --";
75 }
76 } else {
77 result = "-- no result --";
78 }
79 } catch (SQLException sqle) {
80 // If the function does not exist, a SQLException will be thrown, but it should be caught and swallowed if
81 // the non-existent function error message content is found in the error message. The SQLException might
82 // be thrown for some other problem not related to the missing function, so rethrow it if it doesn't
83 // contain the non-existent function error message content.
84 if (!sqle.getMessage().contains(NONEXISTENT_FUNCTION_ERROR_MESSAGE_CONTENT)) {
85 throw sqle;
86 }
87 }
88 return result;
89 }
90
91
92 public static String retrievePostGISServerVersionString(final Connection connection) throws SQLException {
93 Objects.requireNonNull(
94 connection, "Unable to retrieve PostGIS server version string from a null connection"
95 );
96 validateConnection(connection);
97 String postGISVersionString = getVersionString(connection, VersionFunctions.POSTGIS_VERSION.toString());
98 logger.debug("retrieved PostGIS server version string: [{}]", postGISVersionString);
99 return postGISVersionString;
100 }
101
102
103 public static String retrievePostGISServerVersion(final Connection connection) throws SQLException {
104 Objects.requireNonNull(connection, "Unable to retrieve PostGIS version from a null connection");
105 validateConnection(connection);
106 String versionString = retrievePostGISServerVersionString(connection);
107
108 final String versionTerminatorString = " ";
109 final String version;
110 final int versionTerminatorIndex = versionString.indexOf(versionTerminatorString);
111 if (versionTerminatorIndex == -1) {
112 version = versionString;
113 } else {
114 version = versionString.substring(0, versionTerminatorIndex);
115 }
116 logger.debug("retrieved PostGIS server version: [{}]", version);
117 return version;
118 }
119
120
121 public static String retrievePostGISServerMajorVersion(final Connection connection) throws SQLException {
122 Objects.requireNonNull(connection, "Unable to retrieve PostGIS major version from a null connection");
123 validateConnection(connection);
124 String version = retrievePostGISServerVersion(connection);
125 final String majorVersion;
126 final int majorVersionSeperatorIndex = version.indexOf(POSTGIS_SERVER_VERSION_SEPERATOR);
127 if (majorVersionSeperatorIndex == -1) {
128 majorVersion = version;
129 } else {
130 majorVersion = version.substring(0, majorVersionSeperatorIndex);
131 }
132 logger.debug("retrieved postGIS major version string: [{}]", majorVersion);
133 return majorVersion;
134 }
135
136
137 public static String retrievePostGISServerMinorVersion(final Connection connection) throws SQLException {
138 Objects.requireNonNull(connection, "Unable to retrieve PostGIS minor version from a null connection");
139 validateConnection(connection);
140 String version = retrievePostGISServerVersion(connection);
141 final String minorVersion;
142 final int majorVersionSeperatorIndex = version.indexOf(POSTGIS_SERVER_VERSION_SEPERATOR);
143 if (majorVersionSeperatorIndex == -1) {
144 minorVersion = "";
145 } else {
146 final int minorVersionSeperatorIndex =
147 version.indexOf(POSTGIS_SERVER_VERSION_SEPERATOR, majorVersionSeperatorIndex + 1);
148 if (minorVersionSeperatorIndex == -1) {
149 minorVersion = version.substring(majorVersionSeperatorIndex + 1);
150 } else {
151 minorVersion = version.substring(majorVersionSeperatorIndex + 1, minorVersionSeperatorIndex);
152 }
153 }
154 logger.debug("retrieved postGIS minor version string: [{}]", minorVersion);
155 return minorVersion;
156 }
157
158
159 /**
160 * Validates a connection.
161 *
162 * @param connection the connection to be validated.
163 * @throws SQLException when connection is invalid
164 */
165 private static void validateConnection(final Connection connection) throws SQLException {
166 if (!connection.isValid(DEFAULT_CONNECTION_TIMEOUT)) {
167 throw new SQLException("The connection was not valid.");
168 }
169 }
170
171
172 }
+0
-6
postgis-geometry/src/main/java/org/postgis/util/package-info.java less more
0 /**
1 * Utility classes.
2 *
3 * @author Phillip Ross
4 */
5 package org.postgis.util;
+0
-109
postgis-geometry/src/test/java/org/postgis/DatatypesTest.java less more
0 /*
1 * DatatypesTest.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - example and test classes
4 *
5 * (C) 2004 Paul Ramsey, pramsey@refractions.net
6 *
7 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
8 *
9 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 */
26
27 package org.postgis;
28
29
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32 import org.testng.annotations.Test;
33
34 import java.sql.SQLException;
35
36
37 public class DatatypesTest {
38
39 private static final Logger logger = LoggerFactory.getLogger(DatatypesTest.class);
40
41 private static final String mlng_str = "MULTILINESTRING ((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))";
42
43 private static final String mplg_str = "MULTIPOLYGON (((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))";
44
45 private static final String plg_str = "POLYGON ((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))";
46
47 private static final String lng_str = "LINESTRING (10 10 20,20 20 20, 50 50 50, 34 34 34)";
48
49 private static final String ptg_str = "POINT(10 10 20)";
50
51 private static final String lr_str = "(10 10 20,34 34 34, 23 19 23 , 10 10 11)";
52
53
54 @Test
55 public void testLinearRing() throws SQLException {
56 logger.trace("void testLinearRing()");
57 logger.info(lr_str);
58 LinearRing lr = new LinearRing(lr_str);
59 logger.info(lr.toString());
60 }
61
62
63 @Test
64 public void testPoint() throws SQLException {
65 logger.trace("void testPoint()");
66 logger.info(ptg_str);
67 Point ptg = new Point(ptg_str);
68 logger.info(ptg.toString());
69 }
70
71
72 @Test
73 public void testLineString() throws SQLException {
74 logger.trace("void testLineString()");
75 logger.info(lng_str);
76 LineString lng = new LineString(lng_str);
77 logger.info(lng.toString());
78 }
79
80
81 @Test
82 public void testPolygon() throws SQLException {
83 logger.trace("void testPolygon()");
84 logger.info(plg_str);
85 Polygon plg = new Polygon(plg_str);
86 logger.info(plg.toString());
87 }
88
89
90 @Test
91 public void testMultiPolygon() throws SQLException {
92 logger.trace("void testMultiPolygon()");
93 logger.info(mplg_str);
94 MultiPolygon mplg = new MultiPolygon(mplg_str);
95 logger.info(mplg.toString());
96 }
97
98
99 @Test
100 public void testMultiLineString() throws SQLException {
101 logger.trace("void testMultiLineString()");
102 logger.info(mlng_str);
103 MultiLineString mlng = new MultiLineString(mlng_str);
104 logger.info(mlng.toString());
105 }
106
107
108 }
+0
-56
postgis-geometry/src/test/java/org/postgis/TokenizerTest.java less more
0 /*
1 * TokenizerTest.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - example and test classes
4 *
5 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 *
21 */
22
23 package org.postgis;
24
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27 import org.testng.annotations.Test;
28
29 import java.util.List;
30
31
32 public class TokenizerTest {
33
34 private static final Logger logger = LoggerFactory.getLogger(TokenizerTest.class);
35
36
37 @Test
38 public void testTokenizer() {
39 char delimiterL1 = ',';
40 char delimiterL2 = ' ';
41 String stringToTokenize = "((1 2 3),(4 5 6),(7 8 9)";
42 logger.debug("tokenizing string value => {}", stringToTokenize);
43 List<String> tokensLevel1 = GeometryTokenizer.tokenize(GeometryTokenizer.removeLeadingAndTrailingStrings(stringToTokenize, "(", ")"), delimiterL1);
44 logger.debug("level 1 tokens [delimiter = {}] [tokenCount = {}]", delimiterL1, tokensLevel1.size());
45 for (String tokenL1 : tokensLevel1) {
46 logger.debug("L1 token => {} / {}", tokenL1, GeometryTokenizer.removeLeadingAndTrailingStrings(tokenL1, "(", ")"));
47 List<String> tokensLevel2 = GeometryTokenizer.tokenize(GeometryTokenizer.removeLeadingAndTrailingStrings(tokenL1, "(", ")"), delimiterL2);
48 logger.debug("level 2 tokens [delimiter = {}] [tokenCount = {}]", delimiterL2, tokensLevel2.size());
49 for (String tokenL2 : tokensLevel2) {
50 logger.debug("L2 token => {} / {}", tokenL2, GeometryTokenizer.removeLeadingAndTrailingStrings(tokenL2, "(", ")"));
51 }
52 }
53 }
54
55 }
+0
-19
postgis-geometry/src/test/resources/logback-test.xml less more
0 <configuration debug="false">
1
2 <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
3 <layout class="ch.qos.logback.classic.PatternLayout">
4 <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
5 </layout>
6 </appender>
7
8 <root level="debug">
9 <appender-ref ref="STDOUT" />
10 </root>
11
12 <logger name="com.github.dockerjava" level="ERROR"/>
13 <logger name="org.testcontainers" level="ERROR"/>
14 <logger name="net.postgis" level="ERROR"/>
15
16 <logger name="org.postgis" level="ERROR"/>
17
18 </configuration>
+0
-11
postgis-geometry/src/test/resources/testng.xml less more
0 <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
1 <suite name="Postgis Geometry Test Suite" verbose="1">
2
3 <test name="Postgis Geometry Tests">
4 <classes>
5 <class name="org.postgis.DatatypesTest"/>
6 <class name="org.postgis.TokenizerTest"/>
7 </classes>
8 </test>
9
10 </suite>
0
1 GNU LESSER GENERAL PUBLIC LICENSE
2 Version 2.1, February 1999
3
4 Copyright (C) 1991, 1999 Free Software Foundation, Inc.
5 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
6 Everyone is permitted to copy and distribute verbatim copies
7 of this license document, but changing it is not allowed.
8
9 [This is the first released version of the Lesser GPL. It also counts
10 as the successor of the GNU Library Public License, version 2, hence
11 the version number 2.1.]
12
13 Preamble
14
15 The licenses for most software are designed to take away your
16 freedom to share and change it. By contrast, the GNU General Public
17 Licenses are intended to guarantee your freedom to share and change
18 free software--to make sure the software is free for all its users.
19
20 This license, the Lesser General Public License, applies to some
21 specially designated software packages--typically libraries--of the
22 Free Software Foundation and other authors who decide to use it. You
23 can use it too, but we suggest you first think carefully about whether
24 this license or the ordinary General Public License is the better
25 strategy to use in any particular case, based on the explanations
26 below.
27
28 When we speak of free software, we are referring to freedom of use,
29 not price. Our General Public Licenses are designed to make sure that
30 you have the freedom to distribute copies of free software (and charge
31 for this service if you wish); that you receive source code or can get
32 it if you want it; that you can change the software and use pieces of
33 it in new free programs; and that you are informed that you can do
34 these things.
35
36 To protect your rights, we need to make restrictions that forbid
37 distributors to deny you these rights or to ask you to surrender these
38 rights. These restrictions translate to certain responsibilities for
39 you if you distribute copies of the library or if you modify it.
40
41 For example, if you distribute copies of the library, whether gratis
42 or for a fee, you must give the recipients all the rights that we gave
43 you. You must make sure that they, too, receive or can get the source
44 code. If you link other code with the library, you must provide
45 complete object files to the recipients, so that they can relink them
46 with the library after making changes to the library and recompiling
47 it. And you must show them these terms so they know their rights.
48
49 We protect your rights with a two-step method: (1) we copyright the
50 library, and (2) we offer you this license, which gives you legal
51 permission to copy, distribute and/or modify the library.
52
53 To protect each distributor, we want to make it very clear that
54 there is no warranty for the free library. Also, if the library is
55 modified by someone else and passed on, the recipients should know
56 that what they have is not the original version, so that the original
57 author's reputation will not be affected by problems that might be
58 introduced by others.
59
60 Finally, software patents pose a constant threat to the existence of
61 any free program. We wish to make sure that a company cannot
62 effectively restrict the users of a free program by obtaining a
63 restrictive license from a patent holder. Therefore, we insist that
64 any patent license obtained for a version of the library must be
65 consistent with the full freedom of use specified in this license.
66
67 Most GNU software, including some libraries, is covered by the
68 ordinary GNU General Public License. This license, the GNU Lesser
69 General Public License, applies to certain designated libraries, and
70 is quite different from the ordinary General Public License. We use
71 this license for certain libraries in order to permit linking those
72 libraries into non-free programs.
73
74 When a program is linked with a library, whether statically or using
75 a shared library, the combination of the two is legally speaking a
76 combined work, a derivative of the original library. The ordinary
77 General Public License therefore permits such linking only if the
78 entire combination fits its criteria of freedom. The Lesser General
79 Public License permits more lax criteria for linking other code with
80 the library.
81
82 We call this license the "Lesser" General Public License because it
83 does Less to protect the user's freedom than the ordinary General
84 Public License. It also provides other free software developers Less
85 of an advantage over competing non-free programs. These disadvantages
86 are the reason we use the ordinary General Public License for many
87 libraries. However, the Lesser license provides advantages in certain
88 special circumstances.
89
90 For example, on rare occasions, there may be a special need to
91 encourage the widest possible use of a certain library, so that it
92 becomes a de-facto standard. To achieve this, non-free programs must
93 be allowed to use the library. A more frequent case is that a free
94 library does the same job as widely used non-free libraries. In this
95 case, there is little to gain by limiting the free library to free
96 software only, so we use the Lesser General Public License.
97
98 In other cases, permission to use a particular library in non-free
99 programs enables a greater number of people to use a large body of
100 free software. For example, permission to use the GNU C Library in
101 non-free programs enables many more people to use the whole GNU
102 operating system, as well as its variant, the GNU/Linux operating
103 system.
104
105 Although the Lesser General Public License is Less protective of the
106 users' freedom, it does ensure that the user of a program that is
107 linked with the Library has the freedom and the wherewithal to run
108 that program using a modified version of the Library.
109
110 The precise terms and conditions for copying, distribution and
111 modification follow. Pay close attention to the difference between a
112 "work based on the library" and a "work that uses the library". The
113 former contains code derived from the library, whereas the latter must
114 be combined with the library in order to run.
115
116 GNU LESSER GENERAL PUBLIC LICENSE
117 TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
118
119 0. This License Agreement applies to any software library or other
120 program which contains a notice placed by the copyright holder or
121 other authorized party saying it may be distributed under the terms of
122 this Lesser General Public License (also called "this License").
123 Each licensee is addressed as "you".
124
125 A "library" means a collection of software functions and/or data
126 prepared so as to be conveniently linked with application programs
127 (which use some of those functions and data) to form executables.
128
129 The "Library", below, refers to any such software library or work
130 which has been distributed under these terms. A "work based on the
131 Library" means either the Library or any derivative work under
132 copyright law: that is to say, a work containing the Library or a
133 portion of it, either verbatim or with modifications and/or translated
134 straightforwardly into another language. (Hereinafter, translation is
135 included without limitation in the term "modification".)
136
137 "Source code" for a work means the preferred form of the work for
138 making modifications to it. For a library, complete source code means
139 all the source code for all modules it contains, plus any associated
140 interface definition files, plus the scripts used to control
141 compilation and installation of the library.
142
143 Activities other than copying, distribution and modification are not
144 covered by this License; they are outside its scope. The act of
145 running a program using the Library is not restricted, and output from
146 such a program is covered only if its contents constitute a work based
147 on the Library (independent of the use of the Library in a tool for
148 writing it). Whether that is true depends on what the Library does
149 and what the program that uses the Library does.
150
151 1. You may copy and distribute verbatim copies of the Library's
152 complete source code as you receive it, in any medium, provided that
153 you conspicuously and appropriately publish on each copy an
154 appropriate copyright notice and disclaimer of warranty; keep intact
155 all the notices that refer to this License and to the absence of any
156 warranty; and distribute a copy of this License along with the
157 Library.
158
159 You may charge a fee for the physical act of transferring a copy,
160 and you may at your option offer warranty protection in exchange for a
161 fee.
162
163 2. You may modify your copy or copies of the Library or any portion
164 of it, thus forming a work based on the Library, and copy and
165 distribute such modifications or work under the terms of Section 1
166 above, provided that you also meet all of these conditions:
167
168 a) The modified work must itself be a software library.
169
170 b) You must cause the files modified to carry prominent notices
171 stating that you changed the files and the date of any change.
172
173 c) You must cause the whole of the work to be licensed at no
174 charge to all third parties under the terms of this License.
175
176 d) If a facility in the modified Library refers to a function or a
177 table of data to be supplied by an application program that uses
178 the facility, other than as an argument passed when the facility
179 is invoked, then you must make a good faith effort to ensure that,
180 in the event an application does not supply such function or
181 table, the facility still operates, and performs whatever part of
182 its purpose remains meaningful.
183
184 (For example, a function in a library to compute square roots has
185 a purpose that is entirely well-defined independent of the
186 application. Therefore, Subsection 2d requires that any
187 application-supplied function or table used by this function must
188 be optional: if the application does not supply it, the square
189 root function must still compute square roots.)
190
191 These requirements apply to the modified work as a whole. If
192 identifiable sections of that work are not derived from the Library,
193 and can be reasonably considered independent and separate works in
194 themselves, then this License, and its terms, do not apply to those
195 sections when you distribute them as separate works. But when you
196 distribute the same sections as part of a whole which is a work based
197 on the Library, the distribution of the whole must be on the terms of
198 this License, whose permissions for other licensees extend to the
199 entire whole, and thus to each and every part regardless of who wrote
200 it.
201
202 Thus, it is not the intent of this section to claim rights or contest
203 your rights to work written entirely by you; rather, the intent is to
204 exercise the right to control the distribution of derivative or
205 collective works based on the Library.
206
207 In addition, mere aggregation of another work not based on the Library
208 with the Library (or with a work based on the Library) on a volume of
209 a storage or distribution medium does not bring the other work under
210 the scope of this License.
211
212 3. You may opt to apply the terms of the ordinary GNU General Public
213 License instead of this License to a given copy of the Library. To do
214 this, you must alter all the notices that refer to this License, so
215 that they refer to the ordinary GNU General Public License, version 2,
216 instead of to this License. (If a newer version than version 2 of the
217 ordinary GNU General Public License has appeared, then you can specify
218 that version instead if you wish.) Do not make any other change in
219 these notices.
220
221 Once this change is made in a given copy, it is irreversible for
222 that copy, so the ordinary GNU General Public License applies to all
223 subsequent copies and derivative works made from that copy.
224
225 This option is useful when you wish to copy part of the code of
226 the Library into a program that is not a library.
227
228 4. You may copy and distribute the Library (or a portion or
229 derivative of it, under Section 2) in object code or executable form
230 under the terms of Sections 1 and 2 above provided that you accompany
231 it with the complete corresponding machine-readable source code, which
232 must be distributed under the terms of Sections 1 and 2 above on a
233 medium customarily used for software interchange.
234
235 If distribution of object code is made by offering access to copy
236 from a designated place, then offering equivalent access to copy the
237 source code from the same place satisfies the requirement to
238 distribute the source code, even though third parties are not
239 compelled to copy the source along with the object code.
240
241 5. A program that contains no derivative of any portion of the
242 Library, but is designed to work with the Library by being compiled or
243 linked with it, is called a "work that uses the Library". Such a
244 work, in isolation, is not a derivative work of the Library, and
245 therefore falls outside the scope of this License.
246
247 However, linking a "work that uses the Library" with the Library
248 creates an executable that is a derivative of the Library (because it
249 contains portions of the Library), rather than a "work that uses the
250 library". The executable is therefore covered by this License.
251 Section 6 states terms for distribution of such executables.
252
253 When a "work that uses the Library" uses material from a header file
254 that is part of the Library, the object code for the work may be a
255 derivative work of the Library even though the source code is not.
256 Whether this is true is especially significant if the work can be
257 linked without the Library, or if the work is itself a library. The
258 threshold for this to be true is not precisely defined by law.
259
260 If such an object file uses only numerical parameters, data
261 structure layouts and accessors, and small macros and small inline
262 functions (ten lines or less in length), then the use of the object
263 file is unrestricted, regardless of whether it is legally a derivative
264 work. (Executables containing this object code plus portions of the
265 Library will still fall under Section 6.)
266
267 Otherwise, if the work is a derivative of the Library, you may
268 distribute the object code for the work under the terms of Section 6.
269 Any executables containing that work also fall under Section 6,
270 whether or not they are linked directly with the Library itself.
271
272 6. As an exception to the Sections above, you may also combine or
273 link a "work that uses the Library" with the Library to produce a
274 work containing portions of the Library, and distribute that work
275 under terms of your choice, provided that the terms permit
276 modification of the work for the customer's own use and reverse
277 engineering for debugging such modifications.
278
279 You must give prominent notice with each copy of the work that the
280 Library is used in it and that the Library and its use are covered by
281 this License. You must supply a copy of this License. If the work
282 during execution displays copyright notices, you must include the
283 copyright notice for the Library among them, as well as a reference
284 directing the user to the copy of this License. Also, you must do one
285 of these things:
286
287 a) Accompany the work with the complete corresponding
288 machine-readable source code for the Library including whatever
289 changes were used in the work (which must be distributed under
290 Sections 1 and 2 above); and, if the work is an executable linked
291 with the Library, with the complete machine-readable "work that
292 uses the Library", as object code and/or source code, so that the
293 user can modify the Library and then relink to produce a modified
294 executable containing the modified Library. (It is understood
295 that the user who changes the contents of definitions files in the
296 Library will not necessarily be able to recompile the application
297 to use the modified definitions.)
298
299 b) Use a suitable shared library mechanism for linking with the
300 Library. A suitable mechanism is one that (1) uses at run time a
301 copy of the library already present on the user's computer system,
302 rather than copying library functions into the executable, and (2)
303 will operate properly with a modified version of the library, if
304 the user installs one, as long as the modified version is
305 interface-compatible with the version that the work was made with.
306
307 c) Accompany the work with a written offer, valid for at least
308 three years, to give the same user the materials specified in
309 Subsection 6a, above, for a charge no more than the cost of
310 performing this distribution.
311
312 d) If distribution of the work is made by offering access to copy
313 from a designated place, offer equivalent access to copy the above
314 specified materials from the same place.
315
316 e) Verify that the user has already received a copy of these
317 materials or that you have already sent this user a copy.
318
319 For an executable, the required form of the "work that uses the
320 Library" must include any data and utility programs needed for
321 reproducing the executable from it. However, as a special exception,
322 the materials to be distributed need not include anything that is
323 normally distributed (in either source or binary form) with the major
324 components (compiler, kernel, and so on) of the operating system on
325 which the executable runs, unless that component itself accompanies
326 the executable.
327
328 It may happen that this requirement contradicts the license
329 restrictions of other proprietary libraries that do not normally
330 accompany the operating system. Such a contradiction means you cannot
331 use both them and the Library together in an executable that you
332 distribute.
333
334 7. You may place library facilities that are a work based on the
335 Library side-by-side in a single library together with other library
336 facilities not covered by this License, and distribute such a combined
337 library, provided that the separate distribution of the work based on
338 the Library and of the other library facilities is otherwise
339 permitted, and provided that you do these two things:
340
341 a) Accompany the combined library with a copy of the same work
342 based on the Library, uncombined with any other library
343 facilities. This must be distributed under the terms of the
344 Sections above.
345
346 b) Give prominent notice with the combined library of the fact
347 that part of it is a work based on the Library, and explaining
348 where to find the accompanying uncombined form of the same work.
349
350 8. You may not copy, modify, sublicense, link with, or distribute
351 the Library except as expressly provided under this License. Any
352 attempt otherwise to copy, modify, sublicense, link with, or
353 distribute the Library is void, and will automatically terminate your
354 rights under this License. However, parties who have received copies,
355 or rights, from you under this License will not have their licenses
356 terminated so long as such parties remain in full compliance.
357
358 9. You are not required to accept this License, since you have not
359 signed it. However, nothing else grants you permission to modify or
360 distribute the Library or its derivative works. These actions are
361 prohibited by law if you do not accept this License. Therefore, by
362 modifying or distributing the Library (or any work based on the
363 Library), you indicate your acceptance of this License to do so, and
364 all its terms and conditions for copying, distributing or modifying
365 the Library or works based on it.
366
367 10. Each time you redistribute the Library (or any work based on the
368 Library), the recipient automatically receives a license from the
369 original licensor to copy, distribute, link with or modify the Library
370 subject to these terms and conditions. You may not impose any further
371 restrictions on the recipients' exercise of the rights granted herein.
372 You are not responsible for enforcing compliance by third parties with
373 this License.
374
375 11. If, as a consequence of a court judgment or allegation of patent
376 infringement or for any other reason (not limited to patent issues),
377 conditions are imposed on you (whether by court order, agreement or
378 otherwise) that contradict the conditions of this License, they do not
379 excuse you from the conditions of this License. If you cannot
380 distribute so as to satisfy simultaneously your obligations under this
381 License and any other pertinent obligations, then as a consequence you
382 may not distribute the Library at all. For example, if a patent
383 license would not permit royalty-free redistribution of the Library by
384 all those who receive copies directly or indirectly through you, then
385 the only way you could satisfy both it and this License would be to
386 refrain entirely from distribution of the Library.
387
388 If any portion of this section is held invalid or unenforceable under
389 any particular circumstance, the balance of the section is intended to
390 apply, and the section as a whole is intended to apply in other
391 circumstances.
392
393 It is not the purpose of this section to induce you to infringe any
394 patents or other property right claims or to contest validity of any
395 such claims; this section has the sole purpose of protecting the
396 integrity of the free software distribution system which is
397 implemented by public license practices. Many people have made
398 generous contributions to the wide range of software distributed
399 through that system in reliance on consistent application of that
400 system; it is up to the author/donor to decide if he or she is willing
401 to distribute software through any other system and a licensee cannot
402 impose that choice.
403
404 This section is intended to make thoroughly clear what is believed to
405 be a consequence of the rest of this License.
406
407 12. If the distribution and/or use of the Library is restricted in
408 certain countries either by patents or by copyrighted interfaces, the
409 original copyright holder who places the Library under this License
410 may add an explicit geographical distribution limitation excluding those
411 countries, so that distribution is permitted only in or among
412 countries not thus excluded. In such case, this License incorporates
413 the limitation as if written in the body of this License.
414
415 13. The Free Software Foundation may publish revised and/or new
416 versions of the Lesser General Public License from time to time.
417 Such new versions will be similar in spirit to the present version,
418 but may differ in detail to address new problems or concerns.
419
420 Each version is given a distinguishing version number. If the Library
421 specifies a version number of this License which applies to it and
422 "any later version", you have the option of following the terms and
423 conditions either of that version or of any later version published by
424 the Free Software Foundation. If the Library does not specify a
425 license version number, you may choose any version ever published by
426 the Free Software Foundation.
427
428 14. If you wish to incorporate parts of the Library into other free
429 programs whose distribution conditions are incompatible with these,
430 write to the author to ask for permission. For software which is
431 copyrighted by the Free Software Foundation, write to the Free
432 Software Foundation; we sometimes make exceptions for this. Our
433 decision will be guided by the two goals of preserving the free status
434 of all derivatives of our free software and of promoting the sharing
435 and reuse of software generally.
436
437 NO WARRANTY
438
439 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
440 WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
441 EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
442 OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
443 KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
444 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
445 PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
446 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
447 THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
448
449 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
450 WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
451 AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
452 FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
453 CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
454 LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
455 RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
456 FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
457 SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
458 DAMAGES.
459
460 END OF TERMS AND CONDITIONS
461
462 How to Apply These Terms to Your New Libraries
463
464 If you develop a new library, and you want it to be of the greatest
465 possible use to the public, we recommend making it free software that
466 everyone can redistribute and change. You can do so by permitting
467 redistribution under these terms (or, alternatively, under the terms
468 of the ordinary General Public License).
469
470 To apply these terms, attach the following notices to the library.
471 It is safest to attach them to the start of each source file to most
472 effectively convey the exclusion of warranty; and each file should
473 have at least the "copyright" line and a pointer to where the full
474 notice is found.
475
476
477 <one line to give the library's name and a brief idea of what it does.>
478 Copyright (C) <year> <name of author>
479
480 This library is free software; you can redistribute it and/or
481 modify it under the terms of the GNU Lesser General Public
482 License as published by the Free Software Foundation; either
483 version 2.1 of the License, or (at your option) any later version.
484
485 This library is distributed in the hope that it will be useful,
486 but WITHOUT ANY WARRANTY; without even the implied warranty of
487 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
488 Lesser General Public License for more details.
489
490 You should have received a copy of the GNU Lesser General Public
491 License along with this library; if not, write to the Free Software
492 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
493
494 Also add information on how to contact you by electronic and paper mail.
495
496 You should also get your employer (if you work as a programmer) or
497 your school, if any, to sign a "copyright disclaimer" for the library,
498 if necessary. Here is a sample; alter the names:
499
500 Yoyodyne, Inc., hereby disclaims all copyright interest in the
501 library `Frob' (a library for tweaking knobs) written by James
502 Random Hacker.
503
504 <signature of Ty Coon>, 1 April 1990
505 Ty Coon, President of Vice
506
507 That's all there is to it!
508
509
0
1 *** PostGIS JDBC Driver extension README / FAQ ***
2
3 (C) 2005 Markus Schaber <markus.schaber@logix-tt.com>
4
5
6 * What is it all about? *
7
8 JDBC is an database driver specification for Java. Like ODBC in the C
9 world, JDBC allows java applications to transparently use different
10 JDBC compliant databases without any source code changes. PostgreSQL,
11 the database PostGIS is written for, comes with a driver that
12 follows this specification. For downloads and more info, see:
13 http://jdbc.postgresql.org/download.html
14
15 The purpose of the JDBC Driver extension is to give the PostgreSQL
16 JDBC driver some understanding of the PostGIS data types (Geometry,
17 Box3D, Box2D). Without this, the Application can only get byte arrays
18 or strings (binary and text representation, rsp.) and has to parse it
19 on its own. When registering this extension, the Application can
20 simply call getObject(column) on the result of the query, and get a
21 real java object that is modeled after the OpenGIS spec. It also can
22 create or modify this objects itsself and then pass them into the
23 database via the PreparedStatement.setObject() method.
24
25 Currently, the code is tested with PostGIS 0.8.1, 0.9.1. 0.9.2 and
26 1.0.0. It supports both the new hex-encoded EWKB canonical text
27 representation used by PostGIS 1.0.0 lwgeom code, and the old, less
28 efficient WKT like representation used by previous releases when
29 reading data from the server. When sending data to the server, it
30 currently always uses the latter form, which is compatible to all
31 PostGIS versions.
32
33
34 * Do I need it? *
35
36 If you happen to write GIS applications, you can propably benefit.
37
38 In case your applications are PostGIS specific, you can fully exploit
39 the functionality, see "How to I use it" below for instructions and
40 the src/examples directory for some code examples.
41
42 If you rather prefer to stay OpenGIS compliant, then you cannot use
43 the full driver embedding, as this is PostGIS specific functionality.
44 But you can still use the geometry classes as a lightweight java
45 geometry model if you do not want to use a full-blown GIS
46 implementation like jts. Simply use the asText() and
47 GeometryFromText() OpenGIS SQL functions against whichever OpenGIS
48 compliant server you want, and use the WKT parsing constructors or
49 PGgeometry.geomFromString() as well as Geometry.toString() to convert
50 between WKT strings and geometry objects.
51
52
53 * Is it free? *
54
55 Yes. The actual Driver extension code is licensed under the GNU LGPL,
56 this allows everyone to include the code in his projects. You do not
57 have to pay any license fees, and you can keep your own application
58 code proprietary, but you have to make the PostGIS source code available
59 to any receivers, including any modifications you apply to it. For
60 details, please see the license file COPYING_LGPL.
61
62 The Build files and examples are licensed under GNU GPL, just like the
63 rest of PostGIS is. This is not LGPL as applications usually do not
64 link against those.
65
66
67 * How do I build it? *
68
69 There are older make files with which you can try to build, but maven is recommended,
70 as it handles dependencies on a better and cleaner way.
71
72 You have to install maven on your computer to build it. To install maven you can try
73 to search on your software repositories or read the documentation:
74 http://maven.apache.org/download.html
75
76 To compile your postgis driver, go to the jdbc folder and execute the console
77 command "mvn package". This should create a postgis jar on the target folder
78 inside the jdbc folder.
79
80 Note that your postgis driver version does not constrain the PostgreSQL
81 server version. As the JDBC drivers are downwards compatible against older
82 servers, and PostgreSQL servers typically accept older clients, you can
83 easily use e. G. a pgjdbc 8.0 against a PostgreSQL 7.3 server. To benefit
84 from optimizations and bugfixes, it is generally suggested to use the
85 newest stable pgjdbc build that is documented to work against your
86 server release.
87
88 * It is called jdbc2 - does it work with jdbc3, too? *
89
90 To make it short: The naming does not refer to SUN jdbc standard releases
91 jdbc-1, jdbc-2 or jdbc-3.
92
93 The current naming is somehow unfortunate. The directory simply is named
94 jdbc2 because it is the successor of Paul Ramsey's original jdbc directory,
95 which used to exist parallel in the CVS repository. As CVS does its best
96 to hinder useful version tracking across file renames, the name was kept
97 even after removal of the original jdbc subproject.
98
99 Please note that the PostgreSQL JDBC driver itsself is released in
100 several flavours for different JDBC relases and sun JDK releases, but
101 currently, the same postgis.jar should work with all of them. If not,
102 you clearly found a bug, and we kindly ask you to report it.
103
104 If you run into troubles, make shure that you use the newest pgjdbc build.
105 Especially pre releases are known to contain bugs (that's why they are pre
106 releases), and e. G. 8.0 build 309 contained some problems that are fixed
107 in 8.0 build 313.
108
109
110 * How do I use it? *
111
112 To use the PostGIS types, you need the postgis.jar and the pgjdbc
113 driver in your classpath.
114
115 The PostGIS extension must be registered within the JDBC driver.
116 There are three ways to do this:
117
118 - If you use pgjdbc 8.0, the org/postgresql/driverconfig.properties
119 file contained in the postgis.jar autoregisters the PostGIS
120 extension for the PostGIS data types (geometry, box2d, box3d)
121 within the pgjdbc driver.
122
123 - You can use the net.postgis.jdbc.DriverWrapper as replacement for the
124 jdbc driver. This class wraps the PostGreSQL Driver to
125 transparently add the PostGIS Object Classes. This method currently
126 works both with J2EE DataSources, and with the older DriverManager
127 framework. I's a thin wrapper around org.postgresql.Driver that
128 simply registers the extension on every new connection created.
129
130 To use it, you replace the "jdbc:postgresql:" with a
131 "jdbc:postgresql_postGIS" in the jdbc URL, and make your
132 environment aware of the new Driver class.
133
134 DriverManager users simply register net/postgis/DriverWrapper
135 instead of (or in addition to) org.postgresql.Driver, see
136 examples/TestBoxes.connect() for an working code.
137
138 DataSource users similarly have to configure their datasource to
139 use the different class. The following works for jboss, put it in
140 your-ds.xml: <driver-class>net.postgis.jdbc.DriverWrapper</driver-class>
141
142 - Of course, you can also manually register the Datatypes on your
143 pgjdbc connection. You have to cast your connection to PGConnection
144 and then call:
145
146 pgconn.addDataType("geometry", "net.postgis.jdbc.PGgeometry");
147 pgconn.addDataType("box3d", "net.postgis.jdbc.PGbox3d");
148 pgconn.addDataType("box2d", "net.postgis.jdbc.PGbox2d");
149
150 You may need to dig through some wrappers when running in an
151 appserver. E. G. for JBoss, The datasource actually gives you a
152 instance of org.jboss.resource.adapter.jdbc.WrappedConnection and
153 have to call getUnderlyingConnection() on it to get the
154 PGConnection instance.)
155
156 Also note that the above addDataType() methods known from earlier
157 pgjdbc versions are deprecated in pgjdbc 8.0 (but still work), see
158 the commented code variants in the DriverWrapper.addGisTypes()
159 method for an alternative.
160
161 Note: Even using pgjdbc 8.0, you may still want to use the second or
162 third approach if you have several pgjdbc extensions that
163 autoregister for the same PostGIS types, as the driver cannot guess
164 which extension it should actually use on which connection. The
165 current pgjdbc implementation simply parses all
166 org/postgresql/driverconfig.properties the classloader can find in his
167 classpath, using the first definition found for each type.
168
169
170 * How to I run the tests? Are they allowed to fail? *
171
172 There are two types of tests provided, offline and online. Offline
173 tests can run without a PostGIS server, the online tests need a
174 PostGIS server to connect to.
175
176 - Offline Tests
177
178 The easiest way to run the offline tests is "make offlinetests".
179
180 The offline tests should always complete without any failure. If
181 you happen to get a failure here, it is a bug in the PostGIS code
182 (or, very unlikely, in the JDK/JRE or Hardware you use). Please
183 contact the PostGIS developer list in this case.
184
185 - Online tests
186
187 The online tests can be ran with "make onlinetests", but they need
188 a specially prepared database to connect against, and the pgjdbc
189 driver available in your classpath. The Makefile provides defaults
190 for PGHOST, PGPOR, PGDATABASE, PGUSER and PGPASS, you can override
191 them for your needs. For the jtest, the user needs to create and
192 drop table privileges, the two other tests do not use any table.
193 Make shure you have the PostGIS installed in the database.
194
195 None of the online tests should report any failure. However, some of the
196 tests are skipped against PostGix 0.X servers as 0.8.X and 0.9.X, those
197 are the box2d tests (because this datatype simply is missing on those
198 releases), as well as 22 skipped tests for some geometry representations
199 that those old releases do not support. This is a PostGIS server side
200 problem as the server fails to parse some OpenGIS compliant WKT
201 representations, and structurally (but not geometrically or topologically)
202 mangles some other geometries. They are unlikely to be fixed in those
203 releases as users should migrate to PostGIS 1.0.
204
205 The Autoregister Test needs a pgjdbc version 8.0 or newer, and will
206 simply do nothing with older pgjdbc versions.
207
208 If you get any failure messages in the online tests, check whether
209 your really fulfil the prerequisites above. If yes, please contact
210 the PostGIS developer list.
211
212
213 * What about the JTS stuff *
214
215 There's beta support for the JTS 1.6 geometry implementations instead of the
216 native PostGIS classes on the java client side. Simply add jts_1.6.jar to your
217 CLASSPATH, "make postgis_jts" and use at your own risk.
218
219
220 * How can I contact you? *
221
222 Well, the best place are the official PostGIS mailing lists for PostGIS,
223 subscription information is linked at:
224
225 http://postgis.net/
226
227 If you want to report errors, please try to send us all the details we need
228 to reproduce your problem. A small, self-contained test case would be best.
229
230
231 * Phew. That's all? *
232
233 Yes. For now, at least.
234
235 Happy Coding!
0 <?xml version="1.0" encoding="UTF-8"?>
1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
2 <modelVersion>4.0.0</modelVersion>
3
4 <parent>
5 <groupId>net.postgis</groupId>
6 <artifactId>postgis-java-aggregator</artifactId>
7 <version>2021.1.0</version>
8 </parent>
9
10 <artifactId>postgis-jdbc</artifactId>
11 <version>2021.1.0</version>
12 <packaging>jar</packaging>
13
14 <name>Postgis JDBC Driver</name>
15 <description>PostGIS adds support for geographic objects to the PostgreSQL object-relational database.</description>
16
17 <properties />
18
19 <dependencies>
20 <dependency>
21 <groupId>net.postgis</groupId>
22 <artifactId>postgis-geometry</artifactId>
23 <version>2021.1.0</version>
24 </dependency>
25 <dependency>
26 <groupId>org.postgresql</groupId>
27 <artifactId>postgresql</artifactId>
28 <version>${dependency.postgresql-jdbc.version}</version>
29 </dependency>
30 <dependency>
31 <groupId>net.postgis.tools</groupId>
32 <artifactId>test-utils</artifactId>
33 <version>2021.1.0</version>
34 <scope>test</scope>
35 </dependency>
36 </dependencies>
37
38 <build>
39 <plugins>
40 <plugin>
41 <artifactId>maven-jar-plugin</artifactId>
42 <configuration>
43 <archive>
44 <manifestEntries>
45 <Automatic-Module-Name>net.postgis.jdbc</Automatic-Module-Name>
46 </manifestEntries>
47 </archive>
48 </configuration>
49 </plugin>
50 <plugin>
51 <groupId>org.apache.maven.plugins</groupId>
52 <artifactId>maven-failsafe-plugin</artifactId>
53 </plugin>
54 </plugins>
55 </build>
56
57 </project>
0 module net.postgis.jdbc {
1 requires java.sql;
2
3 requires org.postgresql.jdbc;
4
5 requires net.postgis.geometry;
6
7 exports net.postgis.jdbc;
8 }
0 /*
1 * This library is free software; you can redistribute it and/or
2 * modify it under the terms of the GNU Lesser General Public
3 * License as published by the Free Software Foundation; either
4 * version 2.1 of the License, or (at your option) any later version.
5 *
6 * This library is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 * Lesser General Public License for more details.
10 *
11 * You should have received a copy of the GNU Lesser General Public
12 * License along with this library; if not, write to the Free Software
13 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
14 *
15 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
16 *
17 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
18 */
19
20 package net.postgis.jdbc;
21
22
23 import java.sql.Connection;
24 import java.sql.SQLException;
25 import java.util.Properties;
26 import java.util.logging.Level;
27 import java.util.logging.Logger;
28
29 import org.postgresql.Driver;
30 import org.postgresql.PGConnection;
31
32
33 /**
34 * DriverWrapper
35 *
36 * Wraps the PostGreSQL Driver to transparently add the PostGIS Object Classes.
37 * This avoids the need of explicit addDataType() calls from the driver users
38 * side.
39 *
40 * This method currently works with J2EE DataSource implementations, and with
41 * DriverManager framework.
42 *
43 * Simply replace the "jdbc:postgresql:" with a "jdbc:postgresql_postGIS:" in
44 * the jdbc URL.
45 *
46 * When using the drivermanager, you need to initialize DriverWrapper instead of
47 * (or in addition to) org.postgresql.Driver. When using a J2EE DataSource
48 * implementation, set the driver class property in the datasource config, the
49 * following works for jboss:
50 *
51 * <code>
52 * &lt;driver-class&gt;net.postgis.jdbc.DriverWrapper&lt;/driver-class&gt;
53 * </code>
54 * If you don't like or want to use the DriverWrapper, you have two
55 * alternatives, see the README file.
56 *
57 * Also note that the addDataType() methods known from earlier pgjdbc versions
58 * are deprecated in pgjdbc 8.0, see the commented code variants in the
59 * addGisTypes() method.
60 *
61 * This wrapper always uses EWKT as canonical text representation, and thus
62 * works against PostGIS 1.x servers as well as 0.x (tested with 0.8, 0.9 and
63 * 1.0).
64 *
65 * @author {@literal Markus Schaber <markus.schaber@logix-tt.com>}
66 * @see DriverWrapperLW
67 * @see DriverWrapperAutoprobe
68 */
69 public class DriverWrapper extends Driver {
70
71 /** The static logger instance. */
72 protected static final Logger logger = Logger.getLogger("net.postgis.jdbc.DriverWrapper");
73
74 public static final String POSTGRES_PROTOCOL = "jdbc:postgresql:";
75 public static final String POSTGIS_PROTOCOL = "jdbc:postgresql_postGIS:";
76 public static final String REVISION = "$Revision$";
77 protected static TypesAdder ta72 = null;
78 protected static TypesAdder ta74 = null;
79 protected static TypesAdder ta80 = null;
80
81 protected TypesAdder typesAdder;
82
83
84 static {
85 try {
86 // Try to register ourself to the DriverManager
87 java.sql.DriverManager.registerDriver(new DriverWrapper());
88 } catch (SQLException e) {
89 logger.log(Level.WARNING, "Error registering PostGIS Wrapper Driver", e);
90 }
91 }
92
93
94 /**
95 * Default constructor.
96 *
97 * This also loads the appropriate TypesAdder for our SQL Driver instance.
98 *
99 * @throws SQLException when a SQLException occurs
100 */
101 public DriverWrapper() throws SQLException {
102 super();
103 typesAdder = getTypesAdder(this);
104 // The debug method is @since 7.2
105 if (super.getMajorVersion() > 8 || super.getMinorVersion() > 1) {
106 logger.fine(this.getClass().getName() + " loaded TypesAdder: "
107 + typesAdder.getClass().getName());
108 }
109 }
110
111
112 protected static TypesAdder getTypesAdder(final Driver d) throws SQLException {
113 if (d.getMajorVersion() == 7) {
114 if (d.getMinorVersion() >= 3) {
115 if (ta74 == null) {
116 ta74 = loadTypesAdder("74");
117 }
118 return ta74;
119 } else {
120 if (ta72 == null) {
121 ta72 = loadTypesAdder("72");
122 }
123 return ta72;
124 }
125 } else {
126 if (ta80 == null) {
127 ta80 = loadTypesAdder("80");
128 }
129 return ta80;
130 }
131 }
132
133
134 private static TypesAdder loadTypesAdder(final String version) throws SQLException {
135 try {
136 Class klass = Class.forName("net.postgis.jdbc.DriverWrapper$TypesAdder" + version);
137 return (TypesAdder) klass.newInstance();
138 } catch (Exception e) {
139 throw new SQLException("Cannot create TypesAdder instance! " + e.getMessage());
140 }
141 }
142
143
144 /**
145 * Creates a postgresql connection, and then adds the PostGIS data types to it calling addpgtypes().
146 *
147 * A side-effect of this method is that the specified url parameter may be be changed
148 *
149 * @param url the URL of the database to connect to (may be changed as a side-effect of this method)
150 * @param info a list of arbitrary tag/value pairs as connection arguments
151 * @return a connection to the URL or null if it isnt us
152 * @exception SQLException if a database access error occurs
153 *
154 * @see java.sql.Driver#connect
155 * @see org.postgresql.Driver
156 */
157 public java.sql.Connection connect(String url, final Properties info) throws SQLException {
158 url = mangleURL(url);
159 Connection result = super.connect(url, info);
160 typesAdder.addGT(result, useLW(result));
161 return result;
162 }
163
164
165 /**
166 * Do we have HexWKB as well known text representation - to be overridden by
167 * subclasses.
168 *
169 * @param result Connection to check
170 * @return true if using EWKB, false otherwise
171 */
172 protected boolean useLW(final Connection result) {
173 if (result == null) {
174 throw new IllegalArgumentException("null is no valid parameter");
175 }
176 return false;
177 }
178
179
180 /**
181 * Check whether the driver thinks he can handle the given URL.
182 *
183 * A side-effect of this method is that the specified url parameter may be be changed
184 *
185 * @see java.sql.Driver#acceptsURL
186 * @param url the URL of the driver (may be changed as a side-effect of this method)
187 * @return true if this driver accepts the given URL
188 */
189 public boolean acceptsURL(String url) {
190 try {
191 url = mangleURL(url);
192 } catch (SQLException e) {
193 return false;
194 }
195 return super.acceptsURL(url);
196 }
197
198
199 /**
200 * Returns our own CVS version plus postgres Version
201 *
202 * @return String value reprenstation of the version
203 */
204 public static String getVersion() {
205 return "PostGisWrapper " + REVISION + ", wrapping " + Driver.getVersion();
206 }
207
208
209 /*
210 * Here follows the addGISTypes() stuff. This is a little tricky because the
211 * pgjdbc people had several, partially incompatible API changes during 7.2
212 * and 8.0. We still want to support all those releases, however.
213 *
214 */
215 /**
216 * adds the JTS/PostGIS Data types to a PG 7.3+ Connection. If you use
217 * PostgreSQL jdbc drivers V8.0 or newer, those methods are deprecated due
218 * to some class loader problems (but still work for now), and you may want
219 * to use the method below instead.
220 *
221 * @param pgconn The PGConnection object to add the types to
222 * @throws SQLException when a SQLException occurs
223 *
224 */
225 public static void addGISTypes(final PGConnection pgconn) throws SQLException {
226 loadTypesAdder("74").addGT((Connection) pgconn, false);
227 }
228
229
230 /**
231 * adds the JTS/PostGIS Data types to a PG 8.0+ Connection.
232 *
233 * @param pgconn The PGConnection object to add the types to
234 * @throws SQLException when a SQLException occurs
235 */
236 public static void addGISTypes80(final PGConnection pgconn) throws SQLException {
237 loadTypesAdder("80").addGT((Connection) pgconn, false);
238 }
239
240
241 /**
242 * adds the JTS/PostGIS Data types to a PG 7.2 Connection.
243 *
244 * @param pgconn The PGConnection object to add the types to
245 * @throws SQLException when a SQLException occurs
246 */
247 public static void addGISTypes72(final org.postgresql.PGConnection pgconn) throws SQLException {
248 loadTypesAdder("72").addGT((Connection) pgconn, false);
249 }
250
251
252 /**
253 * Mangles the PostGIS URL to return the original PostGreSQL URL
254 *
255 * @param url String containing the url to be "mangled"
256 * @return "mangled" string
257 * @throws SQLException when a SQLException occurs
258 */
259 protected String mangleURL(final String url) throws SQLException {
260 String myProgo = getProtoString();
261 if (url.startsWith(myProgo)) {
262 return POSTGRES_PROTOCOL + url.substring(myProgo.length());
263 } else {
264 throw new SQLException("Unknown protocol or subprotocol in url " + url);
265 }
266 }
267
268
269 protected String getProtoString() {
270 return POSTGIS_PROTOCOL;
271 }
272
273
274 /** Base class for the three typewrapper implementations */
275 protected abstract static class TypesAdder {
276 public final void addGT(final java.sql.Connection conn, final boolean lw) throws SQLException {
277 if (lw) {
278 addBinaryGeometries(conn);
279 } else {
280 addGeometries(conn);
281 }
282 addBoxen(conn);
283 }
284
285 public abstract void addGeometries(final Connection conn) throws SQLException;
286
287 public abstract void addBoxen(final Connection conn) throws SQLException;
288
289 public abstract void addBinaryGeometries(final Connection conn) throws SQLException;
290 }
291
292
293 /** addGISTypes for V7.3 and V7.4 pgjdbc */
294 protected static final class TypesAdder74 extends TypesAdder {
295
296 /** {@inheritDoc} */
297 @Override
298 public void addGeometries(final Connection conn) throws SQLException {
299 PGConnection pgconn = (PGConnection) conn;
300 pgconn.addDataType("geometry", net.postgis.jdbc.PGgeometry.class);
301 pgconn.addDataType("public.geometry", net.postgis.jdbc.PGgeometry.class);
302 pgconn.addDataType("\"public\".\"geometry\"", net.postgis.jdbc.PGgeometry.class);
303
304 pgconn.addDataType("geography", net.postgis.jdbc.PGgeography.class);
305 pgconn.addDataType("public.geography", net.postgis.jdbc.PGgeography.class);
306 pgconn.addDataType("\"public\".\"geography\"", net.postgis.jdbc.PGgeography.class);
307 }
308
309 /** {@inheritDoc} */
310 @Override
311 public void addBoxen(final Connection conn) throws SQLException {
312 PGConnection pgconn = (PGConnection) conn;
313 pgconn.addDataType("box3d", net.postgis.jdbc.PGbox3d.class);
314 pgconn.addDataType("box2d", net.postgis.jdbc.PGbox2d.class);
315 }
316
317 /** {@inheritDoc} */
318 @Override
319 public void addBinaryGeometries(final Connection conn) throws SQLException {
320 PGConnection pgconn = (PGConnection) conn;
321 pgconn.addDataType("geometry", net.postgis.jdbc.PGgeometryLW.class);
322 pgconn.addDataType("geography", net.postgis.jdbc.PGgeographyLW.class);
323 }
324 }
325
326
327 /** addGISTypes for V7.2 pgjdbc */
328 protected static class TypesAdder72 extends TypesAdder {
329
330 /** {@inheritDoc} */
331 @Override
332 public void addGeometries(final Connection conn) throws SQLException {
333 org.postgresql.PGConnection pgconn = (org.postgresql.PGConnection) conn;
334 pgconn.addDataType("geometry", net.postgis.jdbc.PGgeometry.class);
335 pgconn.addDataType("public.geometry", net.postgis.jdbc.PGgeometry.class);
336 pgconn.addDataType("\"public\".\"geometry\"", net.postgis.jdbc.PGgeometry.class);
337
338 pgconn.addDataType("geography", net.postgis.jdbc.PGgeography.class);
339 pgconn.addDataType("public.geography", net.postgis.jdbc.PGgeography.class);
340 pgconn.addDataType("\"public\".\"geography\"", net.postgis.jdbc.PGgeography.class);
341 }
342
343 /** {@inheritDoc} */
344 @Override
345 public void addBoxen(final Connection conn) throws SQLException {
346 org.postgresql.PGConnection pgconn = (org.postgresql.PGConnection) conn;
347 pgconn.addDataType("box3d", net.postgis.jdbc.PGbox3d.class);
348 pgconn.addDataType("box2d", net.postgis.jdbc.PGbox2d.class);
349 }
350
351 /** {@inheritDoc} */
352 @Override
353 public void addBinaryGeometries(final Connection conn) throws SQLException {
354 org.postgresql.PGConnection pgconn = (org.postgresql.PGConnection) conn;
355 pgconn.addDataType("geometry", net.postgis.jdbc.PGgeometryLW.class);
356 pgconn.addDataType("geography", net.postgis.jdbc.PGgeographyLW.class);
357 }
358 }
359
360
361 /** addGISTypes for V8.0 (and hopefully newer) pgjdbc */
362 protected static class TypesAdder80 extends TypesAdder {
363
364 /** {@inheritDoc} */
365 @Override
366 public void addGeometries(final Connection conn) throws SQLException {
367 PGConnection pgconn = (PGConnection) conn;
368 pgconn.addDataType("geometry", net.postgis.jdbc.PGgeometry.class);
369 pgconn.addDataType("public.geometry", net.postgis.jdbc.PGgeometry.class);
370 pgconn.addDataType("\"public\".\"geometry\"", net.postgis.jdbc.PGgeometry.class);
371
372 pgconn.addDataType("geography", net.postgis.jdbc.PGgeometry.class);
373 pgconn.addDataType("public.geography", net.postgis.jdbc.PGgeometry.class);
374 pgconn.addDataType("\"public\".\"geography\"", net.postgis.jdbc.PGgeometry.class);
375 }
376
377 /** {@inheritDoc} */
378 @Override
379 public void addBoxen(final Connection conn) throws SQLException {
380 PGConnection pgconn = (PGConnection) conn;
381 pgconn.addDataType("box3d", net.postgis.jdbc.PGbox3d.class);
382 pgconn.addDataType("box2d", net.postgis.jdbc.PGbox2d.class);
383 }
384
385 /** {@inheritDoc} */
386 @Override
387 public void addBinaryGeometries(final Connection conn) throws SQLException {
388 PGConnection pgconn = (PGConnection) conn;
389 pgconn.addDataType("geometry", net.postgis.jdbc.PGgeometryLW.class);
390 pgconn.addDataType("geography", net.postgis.jdbc.PGgeographyLW.class);
391 }
392 }
393
394
395 /** {@inheritDoc} */
396 @Override
397 public Logger getParentLogger() {
398 throw new UnsupportedOperationException("Not supported yet.");
399 }
400
401
402 }
0 /*
1 * DriverWrapperAutoprobe.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - Wrapper utility class
4 *
5 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
6 *
7 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24
25 package net.postgis.jdbc;
26
27 import org.postgresql.Driver;
28
29 import java.sql.Connection;
30 import java.sql.ResultSet;
31 import java.sql.SQLException;
32 import java.sql.Statement;
33 import java.util.logging.Level;
34
35 /**
36 * DriverWrapperAutoprobe
37 *
38 * Wraps the PostGreSQL Driver to transparently add the PostGIS Object Classes.
39 * This avoids the need of explicit addDataType() calls from the driver users
40 * side.
41 *
42 * This DriverWrapper tries to autoprobe the installed PostGIS version to decide
43 * whether to use EWKT or hex encoded EWKB as canonical text representation. It
44 * uses the first PostGIS installation found in your namespace search path (aka
45 * schema search path) on the server side, and this works as long as you do not
46 * access incompatible PostGIS versions that reside in other schemas.
47 *
48 * For usage notes, see DriverWrapper class, but use "jdbc:postgresql_autogis:"
49 * as JDBC url prefix and net.postgis.jdbc.DriverWrapperAutoprobe as driver class.
50 *
51 * @author {@literal Markus Schaber <markus.schaber@logix-tt.com>}
52 * @see DriverWrapper
53 */
54 public class DriverWrapperAutoprobe extends DriverWrapper {
55
56 public static final String POSTGIS_AUTOPROTOCOL = "jdbc:postgresql_autogis:";
57 public static final String REVISIONAUTO = "$Revision$";
58
59 /**
60 * Default constructor.
61 *
62 * @throws SQLException when a SQLExceptin occurs
63 */
64 public DriverWrapperAutoprobe() throws SQLException {
65 super();
66 }
67
68 static {
69 try {
70 // Try to register ourself to the DriverManager
71 java.sql.DriverManager.registerDriver(new DriverWrapperAutoprobe());
72 } catch (SQLException e) {
73 logger.log(Level.WARNING, "Error registering PostGIS Autoprobe Wrapper Driver", e);
74 }
75 }
76
77 protected String getProtoString() {
78 return POSTGIS_AUTOPROTOCOL;
79 }
80
81 protected boolean useLW(Connection conn) {
82 try {
83 return supportsEWKB(conn);
84 } catch (SQLException e) {
85 // fail safe default
86 return false;
87 }
88 }
89
90 /**
91 * Returns our own CVS version plus postgres Version
92 *
93 * @return String value reprenstation of the version
94 */
95 public static String getVersion() {
96 return "PostGisWrapperAutoprobe " + REVISIONAUTO + ", wrapping " + Driver.getVersion();
97 }
98
99 public static boolean supportsEWKB(Connection conn) throws SQLException {
100 Statement stat = conn.createStatement();
101 ResultSet rs = stat.executeQuery("SELECT postgis_version()");
102 rs.next();
103 String version = rs.getString(1);
104 rs.close();
105 stat.close();
106 if (version == null) {
107 throw new SQLException("postgis_version returned NULL!");
108 }
109 version = version.trim();
110 int idx = version.indexOf('.');
111 int majorVersion = Integer.parseInt(version.substring(0, idx));
112 return majorVersion >= 1;
113 }
114 }
0 /*
1 * DriverWrapperLW.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - Wrapper utility class
4 *
5 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
6 *
7 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24
25 package net.postgis.jdbc;
26
27 import org.postgresql.Driver;
28
29 import java.sql.Connection;
30 import java.sql.SQLException;
31 import java.util.logging.Level;
32
33 /**
34 * DriverWrapperLW
35 *
36 * Wraps the PostGreSQL Driver to transparently add the PostGIS Object Classes.
37 * This avoids the need of explicit addDataType() calls from the driver users
38 * side.
39 *
40 * This DriverWrapper subclass always uses hex encoded EWKB as canonical text
41 * representation, and thus only works against PostGIS 1.x servers and newer.
42 *
43 * For usage notes, see DriverWrapper class, but use "jdbc:postgresql_lwgis:" as
44 * JDBC url prefix and net.postgis.jdbc.DriverWrapperLW as driver class.
45 *
46 * @author {@literal Markus Schaber <markus.schaber@logix-tt.com>}
47 * @see DriverWrapper
48 */
49 public class DriverWrapperLW extends DriverWrapper {
50
51 public static final String POSTGIS_LWPROTOCOL = "jdbc:postgresql_lwgis:";
52 public static final String REVISIONLW = "$Revision$";
53
54 /**
55 * Default constructor.
56 *
57 * @throws SQLException when a SQLException occurs
58 */
59 public DriverWrapperLW() throws SQLException {
60 super();
61 }
62
63 static {
64 try {
65 // Try to register ourself to the DriverManager
66 java.sql.DriverManager.registerDriver(new DriverWrapperLW());
67 } catch (SQLException e) {
68 logger.log(Level.WARNING, "Error registering PostGIS LW Wrapper Driver", e);
69 }
70 }
71
72 protected String getProtoString() {
73 return POSTGIS_LWPROTOCOL;
74 }
75
76 protected boolean useLW(Connection result) {
77 return true;
78 }
79
80 /**
81 * Returns our own CVS version plus postgres Version
82 *
83 * @return String value reprenstation of the version
84 */
85 public static String getVersion() {
86 return "PostGisWrapperLW " + REVISIONLW + ", wrapping " + Driver.getVersion();
87 }
88 }
0 /*
1 * PGbox2d.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - bounding box model
4 *
5 * (C) 2004 Paul Ramsey, pramsey@refractions.net
6 *
7 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
8 *
9 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 */
26
27 package net.postgis.jdbc;
28
29 import net.postgis.jdbc.geometry.Point;
30
31 import java.sql.SQLException;
32
33 public class PGbox2d extends PGboxbase {
34 /* JDK 1.5 Serialization */
35 private static final long serialVersionUID = 0x100;
36
37 public PGbox2d() {
38 super();
39 }
40
41 public PGbox2d(Point llb, Point urt) {
42 super(llb, urt);
43 }
44
45 public PGbox2d(String value) throws SQLException {
46 super(value);
47 }
48
49 public void setValue(String value) throws SQLException {
50 super.setValue(value);
51
52 if (llb.dimension != 2 || urt.dimension != 2) {
53 throw new SQLException("PGbox2d is only allowed to have 2 dimensions!");
54 }
55 }
56
57 public String getPrefix() {
58 return "BOX";
59 }
60
61 public String getPGtype() {
62 return "box2d";
63 }
64
65 protected PGboxbase newInstance() {
66 return new PGbox2d();
67 }
68 }
0 /*
1 * PGbox3d.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - bounding box model
4 *
5 *
6 * (C) 2004 Paul Ramsey, pramsey@refractions.net
7 *
8 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
9 *
10 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
11 *
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
16 *
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
21 *
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 *
26 */
27
28 package net.postgis.jdbc;
29
30 import net.postgis.jdbc.geometry.Point;
31
32 import java.sql.SQLException;
33
34 public class PGbox3d extends PGboxbase {
35 /* JDK 1.5 Serialization */
36 private static final long serialVersionUID = 0x100;
37
38 public PGbox3d() {
39 super();
40 }
41
42 public PGbox3d(Point llb, Point urt) {
43 super(llb, urt);
44 }
45
46 public PGbox3d(String value) throws SQLException {
47 super(value);
48 }
49
50 public String getPrefix() {
51 return ("BOX3D");
52 }
53
54 public String getPGtype() {
55 return ("box3d");
56 }
57
58 protected PGboxbase newInstance() {
59 return new PGbox3d();
60 }
61 }
0 /*
1 * PGboxbase.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - bounding box model
4 *
5 *
6 * (C) 2004 Paul Ramsey, pramsey@refractions.net
7 *
8 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
9 *
10 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
11 *
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
16 *
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
21 *
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 *
26 */
27
28 package net.postgis.jdbc;
29
30 import net.postgis.jdbc.geometry.Geometry;
31 import net.postgis.jdbc.geometry.GeometryBuilder;
32 import net.postgis.jdbc.geometry.GeometryTokenizer;
33 import net.postgis.jdbc.geometry.Point;
34 import org.postgresql.util.PGobject;
35
36 import java.sql.SQLException;
37 import java.util.List;
38
39 /*
40 * Updates Oct 2002 - data members made private - getLLB() and getURT() methods
41 * added
42 */
43
44 public abstract class PGboxbase extends PGobject {
45 /* JDK 1.5 Serialization */
46 private static final long serialVersionUID = 0x100;
47
48 /**
49 * The lower left bottom corner of the box.
50 */
51 protected Point llb;
52
53 /**
54 * The upper right top corner of the box.
55 */
56 protected Point urt;
57
58 /**
59 * The Prefix we have in WKT rep.
60 *
61 * I use an abstract method here so we do not need to replicate the String
62 * object in every instance.
63 *
64 * @return the prefix, as a string
65 */
66 public abstract String getPrefix();
67
68 /**
69 * The Postgres type we have (same construct as getPrefix())
70 *
71 * @return String containing the name of the type for this box.
72 */
73 public abstract String getPGtype();
74
75 public PGboxbase() {
76 this.setType(getPGtype());
77 }
78
79 public PGboxbase(Point llb, Point urt) {
80 this();
81 this.llb = llb;
82 this.urt = urt;
83 }
84
85 public PGboxbase(String value) throws SQLException {
86 this();
87 setValue(value);
88 }
89
90 public void setValue(String value) throws SQLException {
91 int srid = Geometry.UNKNOWN_SRID;
92 value = value.trim();
93 if (value.startsWith("SRID=")) {
94 String[] temp = GeometryBuilder.splitSRID(value);
95 value = temp[1].trim();
96 srid = Geometry.parseSRID(Integer.parseInt(temp[0].substring(5)));
97 }
98 String myPrefix = getPrefix();
99 if (value.startsWith(myPrefix)) {
100 value = value.substring(myPrefix.length()).trim();
101 }
102 String valueNoParans = GeometryTokenizer.removeLeadingAndTrailingStrings(value.trim(), "(", ")");
103 List<String> tokens = GeometryTokenizer.tokenize(valueNoParans, ',');
104 llb = new Point(tokens.get(0));
105 urt = new Point(tokens.get(1));
106 if (srid != Geometry.UNKNOWN_SRID) {
107 llb.setSrid(srid);
108 urt.setSrid(srid);
109 }
110 }
111
112 public String getValue() {
113 StringBuffer sb = new StringBuffer();
114 outerWKT(sb);
115 return sb.toString();
116 }
117
118 private void outerWKT(StringBuffer sb) {
119 sb.append(getPrefix());
120 sb.append('(');
121 llb.innerWKT(sb);
122 sb.append(',');
123 urt.innerWKT(sb);
124 sb.append(')');
125 }
126
127 /**
128 * Unlike geometries, toString() does _not_ contain the srid, as server-side
129 * PostGIS cannot parse this.
130 *
131 * @return String representation of this box
132 */
133 public String toString() {
134 return getValue();
135 }
136
137 /**
138 * Returns the lower left bottom corner of the box as a Point object
139 *
140 * @return lower left bottom corner of this box
141 */
142 public Point getLLB() {
143 return llb;
144 }
145
146 /**
147 * Returns the upper right top corner of the box as a Point object
148 *
149 * @return upper right top corner of this box
150 */
151 public Point getURT() {
152 return urt;
153 }
154
155 public boolean equals(Object other) {
156 if (other instanceof PGboxbase) {
157 PGboxbase otherbox = (PGboxbase) other;
158 return (compareLazyDim(this.llb, otherbox.llb) && compareLazyDim(this.urt, otherbox.urt));
159 }
160 return false;
161 }
162
163 /**
164 * Compare two coordinates with lazy dimension checking.
165 *
166 * As the Server always returns Box3D with three dimensions, z==0 equals
167 * dimensions==2
168 *
169 * @param first First of two points to be compared
170 * @param second Second of two points to be compared
171 * @return true if the points are the same, false otherwise
172 *
173 */
174 protected static boolean compareLazyDim(Point first, Point second) {
175 return first.x == second.x
176 && first.y == second.y
177 && (((first.dimension == 2 || first.z == 0.0) && (second.dimension == 2 || second.z == 0)) || (first.z == second.z));
178 }
179
180 public Object clone() {
181 PGboxbase obj = newInstance();
182 obj.llb = this.llb;
183 obj.urt = this.urt;
184 obj.setType(type);
185 return obj;
186 }
187
188 /**
189 * Obtain a new instance of a PGboxbase
190 *
191 * We could have used this.getClass().newInstance() here, but this forces us
192 * dealing with InstantiationException and IllegalAccessException. Due to
193 * the PGObject.clone() brokennes that does not allow clone() to throw
194 * CloneNotSupportedException, we cannot even pass this exceptions down to
195 * callers in a sane way.
196 *
197 * @return a new instance of PGboxbase
198 */
199 protected abstract PGboxbase newInstance();
200 }
0 /*
1 * This library is free software; you can redistribute it and/or
2 * modify it under the terms of the GNU Lesser General Public
3 * License as published by the Free Software Foundation; either
4 * version 2.1 of the License, or (at your option) any later version.
5 *
6 * This library is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 * Lesser General Public License for more details.
10 *
11 * You should have received a copy of the GNU Lesser General Public
12 * License along with this library; if not, write to the Free Software
13 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
14 *
15 * (C) 2004 Paul Ramsey, pramsey@refractions.net
16 *
17 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
18 *
19 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
20 */
21
22 package net.postgis.jdbc;
23
24
25 import net.postgis.jdbc.geometry.Geometry;
26 import net.postgis.jdbc.geometry.GeometryBuilder;
27 import net.postgis.jdbc.geometry.binary.BinaryParser;
28 import org.postgresql.util.PGobject;
29
30 import java.sql.SQLException;
31
32
33 /**
34 * A PostgreSQL JDBC PGobject extension data type modeling a "geo" type.
35 *
36 * This class serves as a common superclass for classes such as PGgeometry and PGgeography which model
37 * more specific type semantics.
38 *
39 * @author Phillip Ross
40 */
41 public class PGgeo extends PGobject {
42
43 private static final long serialVersionUID = -3181366908975582090L;
44
45 /** The encapsulated geometry. */
46 Geometry geometry;
47
48
49 /** Instantiate with default state. */
50 protected PGgeo() {
51 }
52
53
54 /**
55 * Instantiate with the specified state.
56 *
57 * @param geometry the geometry to instantiate with
58 */
59 public PGgeo(final Geometry geometry) {
60 this();
61 this.geometry = geometry;
62 }
63
64
65 /**
66 * Instantiate with the specified state.
67 *
68 * @param value the value to instantiate with
69 */
70 public PGgeo(final String value) throws SQLException {
71 this();
72 setValue(value);
73 }
74
75
76 /** {@inheritDoc} */
77 @Override
78 public String getValue() {
79 return geometry.toString();
80 }
81
82
83 /** {@inheritDoc} */
84 @Override
85 public void setValue(final String value) throws SQLException {
86 geometry = GeometryBuilder.geomFromString(value, new BinaryParser());
87 }
88
89
90 /**
91 * Get the encapsulated geometry.
92 *
93 * @return the encapsulated geomtery
94 */
95 public Geometry getGeometry() {
96 return geometry;
97 }
98
99
100 /**
101 * Set the encapsulated geometry.
102 *
103 * @param geometry the encapsulated geometry
104 */
105 public void setGeometry(final Geometry geometry) {
106 this.geometry = geometry;
107 }
108
109
110 /**
111 * Get the type of the encapsulated geometry.
112 *
113 * @return the type of the encapsulated geometry
114 */
115 public int getGeoType() {
116 return geometry.type;
117 }
118
119
120 /** {@inheritDoc} */
121 @Override
122 public String toString() {
123 return geometry.toString();
124 }
125
126
127 /** {@inheritDoc} */
128 @Override
129 public Object clone() {
130 return new PGgeo(geometry);
131 }
132
133
134 }
0 /*
1 * This library is free software; you can redistribute it and/or
2 * modify it under the terms of the GNU Lesser General Public
3 * License as published by the Free Software Foundation; either
4 * version 2.1 of the License, or (at your option) any later version.
5 *
6 * This library is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 * Lesser General Public License for more details.
10 *
11 * You should have received a copy of the GNU Lesser General Public
12 * License along with this library; if not, write to the Free Software
13 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
14 *
15 * (C) 2004 Paul Ramsey, pramsey@refractions.net
16 *
17 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
18 *
19 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
20 */
21
22 package net.postgis.jdbc;
23
24
25 import net.postgis.jdbc.geometry.Geometry;
26
27 import java.sql.SQLException;
28
29
30 /**
31 * A PostgreSQL JDBC PGobject extension data type modeling the geography type.
32 *
33 * @author Phillip Ross
34 */
35 public class PGgeography extends PGgeo {
36
37 private static final long serialVersionUID = 3796853960196603896L;
38
39
40 /** Instantiate with default state. */
41 public PGgeography() {
42 super();
43 setType("geography");
44 }
45
46
47 /**
48 * Instantiate with the specified state.
49 *
50 * @param geometry the geometry to instantiate with
51 */
52 public PGgeography(final Geometry geometry) {
53 this();
54 this.geometry = geometry;
55 setType("geography");
56 }
57
58
59 /**
60 * Instantiate with the specified state.
61 *
62 * @param value the value to instantiate with
63 */
64 public PGgeography(final String value) throws SQLException {
65 this();
66 setValue(value);
67 setType("geography");
68 }
69
70
71 /** {@inheritDoc} */
72 @Override
73 public Object clone() {
74 return new PGgeography(geometry);
75 }
76
77
78 }
0 /*
1 * This library is free software; you can redistribute it and/or
2 * modify it under the terms of the GNU Lesser General Public
3 * License as published by the Free Software Foundation; either
4 * version 2.1 of the License, or (at your option) any later version.
5 *
6 * This library is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 * Lesser General Public License for more details.
10 *
11 * You should have received a copy of the GNU Lesser General Public
12 * License along with this library; if not, write to the Free Software
13 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
14 *
15 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
16 *
17 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
18 */
19
20 package net.postgis.jdbc;
21
22
23 import net.postgis.jdbc.geometry.Geometry;
24 import net.postgis.jdbc.geometry.binary.BinaryWriter;
25
26 import java.sql.SQLException;
27
28
29 /**
30 * A PostgreSQL JDBC PGobject extension data type modeling the geography type.
31 *
32 * The hex-encoded EWKB format is used to communicate with the backend, which is much more efficient,
33 * but only works with Lwgeom enabled PostGIS (1.0.0 and up).
34 *
35 * @author Phillip Ross
36 */
37 public class PGgeographyLW extends PGgeography {
38
39 private static final long serialVersionUID = 7717856818804158022L;
40
41 /** The binary writer to be used for serializing geometry to a PGobject value. */
42 BinaryWriter bw = new BinaryWriter();
43
44
45 /** Instantiate with default state. */
46 public PGgeographyLW() {
47 super();
48 }
49
50 /**
51 * Instantiate with the specified state.
52 *
53 * @param geometry the geometry to instantiate with
54 */
55 public PGgeographyLW(final Geometry geometry) {
56 super(geometry);
57 }
58
59
60 /**
61 * Instantiate with the specified state.
62 *
63 * @param value the value to instantiate with
64 */
65 public PGgeographyLW(final String value) throws SQLException {
66 super(value);
67 }
68
69
70 /** {@inheritDoc} */
71 @Override
72 public String getValue() {
73 return bw.writeHexed(geometry);
74 }
75
76
77 /** {@inheritDoc} */
78 @Override
79 public Object clone() {
80 return new PGgeographyLW(geometry);
81 }
82
83
84 }
0 /*
1 * This library is free software; you can redistribute it and/or
2 * modify it under the terms of the GNU Lesser General Public
3 * License as published by the Free Software Foundation; either
4 * version 2.1 of the License, or (at your option) any later version.
5 *
6 * This library is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 * Lesser General Public License for more details.
10 *
11 * You should have received a copy of the GNU Lesser General Public
12 * License along with this library; if not, write to the Free Software
13 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
14 *
15 * (C) 2004 Paul Ramsey, pramsey@refractions.net
16 *
17 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
18 *
19 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
20 */
21
22 package net.postgis.jdbc;
23
24
25 import net.postgis.jdbc.geometry.Geometry;
26
27 import java.sql.SQLException;
28
29
30 /**
31 * A PostgreSQL JDBC PGobject extension data type modeling the geometry type.
32 *
33 * @author Phillip Ross
34 */
35 public class PGgeometry extends PGgeo {
36
37 private static final long serialVersionUID = 4116907189503026815L;
38
39
40 /** Instantiate with default state. */
41 public PGgeometry() {
42 super();
43 setType("geometry");
44 }
45
46
47 /**
48 * Instantiate with the specified state.
49 *
50 * @param geometry the geometry to instantiate with
51 */
52 public PGgeometry(final Geometry geometry) {
53 super(geometry);
54 setType("geometry");
55 }
56
57
58 /**
59 * Instantiate with the specified state.
60 *
61 * @param value the value to instantiate with
62 */
63 public PGgeometry(final String value) throws SQLException {
64 super(value);
65 setType("geometry");
66 }
67
68
69 /** {@inheritDoc} */
70 @Override
71 public Object clone() {
72 return new PGgeometry(geometry);
73 }
74
75
76 }
0 /*
1 * This library is free software; you can redistribute it and/or
2 * modify it under the terms of the GNU Lesser General Public
3 * License as published by the Free Software Foundation; either
4 * version 2.1 of the License, or (at your option) any later version.
5 *
6 * This library is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 * Lesser General Public License for more details.
10 *
11 * You should have received a copy of the GNU Lesser General Public
12 * License along with this library; if not, write to the Free Software
13 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
14 *
15 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
16 *
17 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
18 */
19
20 package net.postgis.jdbc;
21
22
23 import net.postgis.jdbc.geometry.Geometry;
24 import net.postgis.jdbc.geometry.binary.BinaryWriter;
25
26 import java.sql.SQLException;
27
28
29 /**
30 * A PostgreSQL JDBC PGobject extension data type modeling the geometry type.
31 *
32 * The hex-encoded EWKB format is used to communicate with the backend, which is much more efficient,
33 * but only works with Lwgeom enabled PostGIS (1.0.0 and up).
34 *
35 * @author Phillip Ross
36 */
37 public class PGgeometryLW extends PGgeometry {
38
39 private static final long serialVersionUID = -7774502289413094862L;
40
41 /** The binary writer to be used for serializing geometry to a PGobject value. */
42 BinaryWriter bw = new BinaryWriter();
43
44
45 /** Instantiate with default state. */
46 public PGgeometryLW() {
47 super();
48 }
49
50
51 /**
52 * Instantiate with the specified state.
53 *
54 * @param geometry the geometry to instantiate with
55 */
56 public PGgeometryLW(final Geometry geometry) {
57 super(geometry);
58 }
59
60
61 /**
62 * Instantiate with the specified state.
63 *
64 * @param value the value to instantiate with
65 */
66 public PGgeometryLW(final String value) throws SQLException {
67 super(value);
68 }
69
70
71 /** {@inheritDoc} */
72 @Override
73 public String getValue() {
74 return bw.writeHexed(geometry);
75 }
76
77
78 /** {@inheritDoc} */
79 @Override
80 public Object clone() {
81 return new PGgeometryLW(geometry);
82 }
83
84
85 }
0 /*
1 * Version.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - current version identification
4 *
5 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
6 *
7 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24
25 package net.postgis.jdbc;
26
27
28 import java.io.IOException;
29 import java.util.Properties;
30
31
32 /** Corresponds to the appropriate PostGIS that carried this source */
33 public class Version {
34
35 /** We read our version information from this resource... */
36 private static final String RESOURCE_FILENAME = "net/postgis/jdbc/version.properties";
37
38 private static final String VERSION_PROPERTY_NAME = "VERSION";
39
40 public static final String VERSION;
41
42 /** The major version */
43 public static final int MAJOR;
44
45 /** The minor version */
46 public static final int MINOR;
47
48 /**
49 * The micro version, usually a number including possibly textual suffixes
50 * like RC3.
51 */
52 public static final String MICRO;
53
54 static {
55 int major = -1;
56 int minor = -1;
57 String micro = null;
58 String version = null;
59 try {
60 ClassLoader loader = Version.class.getClassLoader();
61
62 Properties prop = new Properties();
63 try {
64 prop.load(loader.getResourceAsStream(RESOURCE_FILENAME));
65 } catch (IOException e) {
66 throw new ExceptionInInitializerError("Error initializing PostGIS JDBC version. Cause: Ressource "
67 + RESOURCE_FILENAME + " cannot be read. " + e.getMessage());
68 } catch (NullPointerException e) {
69 throw new ExceptionInInitializerError("Error initializing PostGIS JDBC version. Cause: Ressource "
70 + RESOURCE_FILENAME + " not found. " + e.getMessage());
71 }
72
73 version = prop.getProperty(VERSION_PROPERTY_NAME);
74 if (version == null) {
75 throw new ExceptionInInitializerError("Error initializing PostGIS JDBC version: Missing " + VERSION_PROPERTY_NAME + " property.");
76 } else if (version.equals("")) {
77 throw new ExceptionInInitializerError("Error initializing PostGIS JDBC version: Empty " + VERSION_PROPERTY_NAME + " property.");
78 } else {
79 String[] versions = version.split("\\.");
80 if (version.length() < 3) {
81 throw new ExceptionInInitializerError("Error initializing PostGIS JDBC version: FULL_VERSION (" + version + ") does not contain 3 components ");
82 }
83 if (versions.length >= 1) {
84 try {
85 major = Integer.parseInt(versions[0]);
86 } catch (NumberFormatException nfe) {
87 throw new ExceptionInInitializerError("Error initializing PostGIS JDBC version! Error parsing major version ");
88 }
89 }
90 if (versions.length >= 2) {
91 try {
92 minor = Integer.parseInt(versions[1]);
93 } catch (NumberFormatException nfe) {
94 throw new ExceptionInInitializerError("Error initializing PostGIS JDBC version! Error parsing minor version ");
95 }
96 }
97 if (version.length() >= 3) {
98 micro = versions[2];
99 }
100 }
101
102 } finally {
103 MAJOR = major;
104 MINOR = minor;
105 MICRO = micro;
106 VERSION = version;
107 }
108 }
109
110 /** Full version for human reading - code should use the constants above */
111 public static final String FULL = "PostGIS JDBC V" + MAJOR + "." + MINOR + "." + MICRO;
112
113 public static String getFullVersion() {
114 return FULL;
115 }
116
117
118 }
0 <body>
1 <p>The JDBC extensions provide Java objects corresponding to the internal PostGIS types. These objects can be used
2 to write Java clients which query the PostGIS database and draw or do calculations on the GIS data in PostGIS.
3 </p>
4 </body>
0 net.postgis.jdbc.DriverWrapper
1 net.postgis.jdbc.DriverWrapperAutoprobe
2 net.postgis.jdbc.DriverWrapperLW
0 #
1 # This property file is included in the postgis jar and autoregisters the
2 # PostGIS datatypes within the jdbc driver.
3 #
4
5 datatype.geometry=net.postgis.jdbc.PGgeometry
6 datatype.geography=net.postgis.jdbc.PGgeography
7 datatype.box3d=net.postgis.jdbc.PGbox3d
8 datatype.box2d=net.postgis.jdbc.PGbox2d
0 /*
1 * BoxesTest.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - example and test classes
4 *
5 * (C) 2004 Paul Ramsey, pramsey@refractions.net
6 *
7 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
8 *
9 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 */
26
27 package net.postgis.jdbc;
28
29
30 import net.postgis.tools.testutils.TestContainerController;
31 import net.postgis.jdbc.geometry.util.VersionUtil;
32 import org.postgresql.util.PGobject;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35 import org.testng.Assert;
36 import org.testng.ITestContext;
37 import org.testng.annotations.AfterClass;
38 import org.testng.annotations.BeforeClass;
39 import org.testng.annotations.Test;
40
41 import java.sql.*;
42
43
44 public class BoxesTest {
45
46 private static final Logger logger = LoggerFactory.getLogger(BoxesTest.class);
47
48 /** Our test candidates: */
49 public static final String[] BOXEN3D = new String[]{
50 "BOX3D(1 2 3,4 5 6)", // 3d variant
51 "BOX3D(1 2,4 5)"// 2d variant
52 };
53
54 public static final String[] BOXEN2D = new String[]{"BOX(1 2,3 4)"};
55
56 private Connection connection = null;
57
58
59 @Test
60 public void testBoxes() throws Exception {
61 for (String aBOXEN3D : BOXEN3D) {
62 PGbox3d candidate = new PGbox3d(aBOXEN3D);
63 test(aBOXEN3D, candidate, false);
64 }
65 for (String aBOXEN2D : BOXEN2D) {
66 PGbox2d candidate = new PGbox2d(aBOXEN2D);
67 test(aBOXEN2D, candidate, true);
68 }
69 }
70
71
72 public void test(String orig, PGobject candidate, boolean newPostgisOnly) throws Exception {
73 logger.debug("Original: {}", orig);
74 String redone = candidate.toString();
75 logger.debug("Parsed: {}", redone);
76 Assert.assertEquals(orig, redone, "Recreated Text Rep not equal");
77
78 // Simulate the way postgresql-jdbc uses to create PGobjects
79 PGobject recreated = candidate.getClass().newInstance();
80 recreated.setValue(redone);
81
82 String reparsed = recreated.toString();
83 logger.debug("Re-Parsed: " + reparsed);
84 Assert.assertEquals(recreated, candidate, "Recreated boxen are not equal");
85 Assert.assertEquals(reparsed, orig, "2nd generation text reps are not equal");
86
87 logger.debug("testing on connection: {}", connection.getCatalog());
88 Statement statement = connection.createStatement();
89 if (newPostgisOnly && Integer.parseInt(VersionUtil.retrievePostGISServerMajorVersion(connection)) < 1) {
90 logger.debug("PostGIS version is too old, not testing box2d");
91 } else {
92 PGobject sqlGeom = viaSQL(candidate, statement);
93 logger.debug("SQLin : " + sqlGeom.toString());
94 Assert.assertEquals(candidate, sqlGeom, "Geometries after SQL are not equal");
95 PGobject sqlreGeom = viaSQL(recreated, statement);
96 logger.debug("SQLout : " + sqlreGeom.toString());
97 Assert.assertEquals(candidate, sqlreGeom, "reparsed Geometries after SQL are not equal");
98 }
99 statement.close();
100 }
101
102
103 /** Pass a geometry representation through the SQL server */
104 private static PGobject viaSQL(PGobject obj, Statement stat) throws SQLException {
105 ResultSet rs = stat.executeQuery("SELECT '" + obj.toString() + "'::" + obj.getType());
106 rs.next();
107 return (PGobject) rs.getObject(1);
108 }
109
110
111 @BeforeClass
112 public void initJdbcConnection(ITestContext ctx) throws Exception {
113 final String jdbcUrlSuffix = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_JDBC_URL_SUFFIX);
114 Assert.assertNotNull(jdbcUrlSuffix);
115 final String jdbcUrl = "jdbc:postgresql" + jdbcUrlSuffix;
116 final String jdbcUsername = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_USER_PARAM_NAME);
117 Assert.assertNotNull(jdbcUsername);
118 final String jdbcPassword = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_PW_PARAM_NAME);
119 Assert.assertNotNull(jdbcPassword);
120 Class.forName("net.postgis.jdbc.DriverWrapper");
121 connection = DriverManager.getConnection(jdbcUrl, jdbcUsername, jdbcPassword);
122 }
123
124
125 @AfterClass
126 public void shutdown() throws Exception {
127 logger.debug("shutting down");
128 if (connection != null) {
129 connection.close();
130 }
131 }
132
133
134 }
0 /*
1 * This library is free software; you can redistribute it and/or
2 * modify it under the terms of the GNU Lesser General Public
3 * License as published by the Free Software Foundation; either
4 * version 2.1 of the License, or (at your option) any later version.
5 *
6 * This library is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 * Lesser General Public License for more details.
10 *
11 * You should have received a copy of the GNU Lesser General Public
12 * License along with this library; if not, write to the Free Software
13 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
14 *
15 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
16 *
17 * (C) 2020 Phillip Ross, phillip.w.g.ross@gmail.com
18 */
19
20 package net.postgis.jdbc;
21
22
23 import net.postgis.tools.testutils.TestContainerController;
24 import net.postgis.jdbc.geometry.util.VersionUtil;
25 import org.postgresql.Driver;
26 import org.postgresql.util.PGobject;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
29 import org.testng.Assert;
30 import org.testng.ITestContext;
31 import org.testng.annotations.AfterMethod;
32 import org.testng.annotations.BeforeMethod;
33 import org.testng.annotations.Test;
34
35 import java.sql.Connection;
36 import java.sql.DriverManager;
37 import java.sql.ResultSet;
38 import java.sql.Statement;
39
40
41 /**
42 * This test program tests whether the auto-registration of PostGIS data types within the postgresql jdbc driver was
43 * successful. It also checks for PostGIS version to know whether box2d is available.
44 */
45 public class DatatypesAutoRegistrationTest {
46
47 /** The static logger instance. */
48 private static final Logger logger = LoggerFactory.getLogger(DatatypesAutoRegistrationTest.class);
49
50 /** The JDBC Connection to be used for tests. */
51 private Connection connection;
52
53
54 /**
55 * Initializes a new JDBC Connection.
56 *
57 * @param ctx the test context
58 * @throws Exception when an exception occurs
59 */
60 @BeforeMethod
61 public void initJdbcConnection(ITestContext ctx) throws Exception {
62 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
63 final String jdbcUrlSuffix = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_JDBC_URL_SUFFIX);
64 Assert.assertNotNull(jdbcUrlSuffix);
65 final String jdbcUrl = "jdbc:postgresql" + jdbcUrlSuffix;
66 final String jdbcUsername = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_USER_PARAM_NAME);
67 Assert.assertNotNull(jdbcUsername);
68 final String jdbcPassword = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_PW_PARAM_NAME);
69 Assert.assertNotNull(jdbcPassword);
70 connection = DriverManager.getConnection(jdbcUrl, jdbcUsername, jdbcPassword);
71 }
72
73
74 /**
75 * Un-allocates the JDBC connection.
76 *
77 * @throws Exception when an exception occurs
78 */
79 @AfterMethod
80 public void shutdown() throws Exception {
81 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
82 logger.debug("shutting down");
83 if (connection != null) {
84 connection.close();
85 }
86 }
87
88
89 @Test
90 public void testAutoRegistration() throws Exception {
91 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
92 Driver driver = new Driver();
93 int driverMajorVersion = driver.getMajorVersion();
94 int driverMinorVersion = driver.getMinorVersion();
95 logger.debug("Driver version: {}.{}", driverMajorVersion, driverMinorVersion);
96 if (driverMajorVersion < 8) {
97 logger.info(
98 "postgresql driver {}.{} is too old, it does not support auto-registration",
99 driverMajorVersion, driverMinorVersion
100 );
101 } else {
102 int postgisServerMajor = Integer.parseInt(VersionUtil.retrievePostGISServerMajorVersion(connection));
103 logger.debug("PostGIS Version: " + postgisServerMajor);
104 Assert.assertNotEquals(
105 postgisServerMajor,
106 0,
107 "Could not get PostGIS version. Is PostGIS really installed in the database?"
108 );
109 Statement statement = connection.createStatement();
110
111 // Test geometries
112 ResultSet resultSet = statement.executeQuery("SELECT 'POINT(1 2)'::geometry");
113 resultSet.next();
114 PGobject result = (PGobject) resultSet.getObject(1);
115 Assert.assertTrue(result instanceof PGgeometry);
116
117 // Test geography
118 resultSet = statement.executeQuery("SELECT 'POINT(1 2)'::geography");
119 resultSet.next();
120 Object geographyRawObject = resultSet.getObject(1);
121 result = (PGobject) resultSet.getObject(1);
122 Assert.assertTrue(result instanceof PGgeography);
123
124 // Test box3d
125 resultSet = statement.executeQuery("SELECT 'BOX3D(1 2 3, 4 5 6)'::box3d");
126 resultSet.next();
127 result = (PGobject) resultSet.getObject(1);
128 Assert.assertTrue(result instanceof PGbox3d);
129
130 // Test box2d if appropriate
131 if (postgisServerMajor < 1) {
132 logger.info("PostGIS version is too old, skipping box2ed test");
133 } else {
134 resultSet = statement.executeQuery("SELECT 'BOX(1 2,3 4)'::box2d");
135 resultSet.next();
136 result = (PGobject) resultSet.getObject(1);
137 Assert.assertTrue(result instanceof PGbox2d);
138 }
139 }
140 }
141
142
143 }
0 /*
1 * DatatypesTest.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - example and test classes
4 *
5 * (C) 2004 Paul Ramsey, pramsey@refractions.net
6 *
7 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
8 *
9 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 */
26
27 package net.postgis.jdbc;
28
29
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32 import org.testng.annotations.Test;
33
34 import java.sql.SQLException;
35
36
37 public class DatatypesTest {
38
39 private static final Logger logger = LoggerFactory.getLogger(DatatypesTest.class);
40
41 private static final String mlng_str = "MULTILINESTRING ((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))";
42
43
44 @Test
45 public void testPGgeometry() throws SQLException {
46 logger.trace("void testPGgeometry()");
47 logger.info(mlng_str);
48 PGgeometry pgf = new PGgeometry(mlng_str);
49 logger.info(pgf.toString());
50 }
51
52
53 @Test
54 public void testPGgeography() throws SQLException {
55 logger.trace("void testPGgeography()");
56 logger.info(mlng_str);
57 PGgeography pgf = new PGgeography(mlng_str);
58 logger.info(pgf.toString());
59 }
60
61
62 }
0 /*
1 * EmptyGeometriesTest.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - example and test classes
4 *
5 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 *
21 */
22
23 package net.postgis.jdbc;
24
25
26 import net.postgis.tools.testutils.TestContainerController;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
29 import org.testng.Assert;
30 import org.testng.ITestContext;
31 import org.testng.annotations.AfterClass;
32 import org.testng.annotations.BeforeClass;
33 import org.testng.annotations.Test;
34
35 import java.sql.*;
36 import java.util.ArrayList;
37 import java.util.List;
38
39
40 /**
41 * This class contains tests for handling of empty geometries.
42 *
43 * @author Phillip Ross {@literal <phillip.r.g.ross@gmail.com>}
44 */
45 public class EmptyGeometriesTest {
46
47 private static final Logger logger = LoggerFactory.getLogger(EmptyGeometriesTest.class);
48
49 private static final String DRIVER_WRAPPER_CLASS_NAME = "net.postgis.jdbc.DriverWrapper";
50
51 private static final String DRIVER_WRAPPER_AUTOPROBE_CLASS_NAME = "net.postgis.jdbc.DriverWrapperAutoprobe";
52
53
54 public static final String[] geometriesToTest = new String[] {
55 "POINT",
56 "LINESTRING",
57 "POLYGON",
58 "MULTIPOINT",
59 "MULTILINESTRING",
60 "MULTIPOLYGON",
61 "GEOMETRYCOLLECTION",
62 };
63
64 public static final String[] castTypes = new String[] {
65 "bytea",
66 "text",
67 "geometry",
68 "geography"
69 };
70
71 private Connection connection = null;
72
73 private Statement statement = null;
74
75
76 @Test
77 public void testSqlStatements() throws SQLException {
78 for (String sqlStatement : generateSqlStatements()) {
79 logger.debug("**********");
80 logger.debug("* Executing sql statemnent => [{}]", sqlStatement);
81 logger.debug("**********");
82 try (PreparedStatement preparedStatement = connection.prepareStatement(sqlStatement);
83 ResultSet resultSet = preparedStatement.executeQuery()
84 ) {
85 resultSet.next();
86 for (int i = 1; i <= castTypes.length; i++) {
87 Object resultSetObject = resultSet.getObject(i);
88 logger.debug("returned resultSetObject {} => (class=[{}]) {}", i, resultSetObject.getClass().getName(), resultSetObject);
89 }
90 resultSet.close();
91 }
92 }
93 }
94
95
96 private List<String> generateSqlStatements() {
97 List<String> sqlStatementList = new ArrayList<>();
98 for (String geometry : geometriesToTest) {
99 StringBuilder stringBuilder = new StringBuilder("select ");
100 for (String castType : castTypes) {
101 stringBuilder.append("geometry_in('")
102 .append(geometry)
103 .append(" EMPTY')::")
104 .append(castType)
105 .append(", ");
106 }
107 String sqlStatement = stringBuilder.substring(0, stringBuilder.lastIndexOf(","));
108 logger.debug("generate sql statement: {}", sqlStatement);
109 sqlStatementList.add(sqlStatement);
110 }
111 return sqlStatementList;
112 }
113
114
115 @BeforeClass
116 public void initJdbcConnection(ITestContext ctx) throws Exception {
117 final String jdbcUrlSuffix = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_JDBC_URL_SUFFIX);
118 Assert.assertNotNull(jdbcUrlSuffix);
119 final String jdbcUrl = "jdbc:postgresql" + jdbcUrlSuffix;
120 final String jdbcUsername = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_USER_PARAM_NAME);
121 Assert.assertNotNull(jdbcUsername);
122 final String jdbcPassword = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_PW_PARAM_NAME);
123 Assert.assertNotNull(jdbcPassword);
124 Class.forName(DRIVER_WRAPPER_CLASS_NAME);
125 Class.forName(DRIVER_WRAPPER_AUTOPROBE_CLASS_NAME);
126 connection = DriverManager.getConnection(jdbcUrl, jdbcUsername, jdbcPassword);
127 statement = connection.createStatement();
128 }
129
130
131 @AfterClass
132 public void unallocateDatabaseResources() throws Exception {
133 if ((statement != null) && (!statement.isClosed())) {
134 statement.close();
135 }
136 if ((connection != null) && (!connection.isClosed())) {
137 connection.close();
138 }
139 }
140
141
142 }
0 /*
1 * This library is free software; you can redistribute it and/or
2 * modify it under the terms of the GNU Lesser General Public
3 * License as published by the Free Software Foundation; either
4 * version 2.1 of the License, or (at your option) any later version.
5 *
6 * This library is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 * Lesser General Public License for more details.
10 *
11 * You should have received a copy of the GNU Lesser General Public
12 * License along with this library; if not, write to the Free Software
13 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
14 *
15 * (C) 2020 Phillip Ross, phillip.w.g.ross@gmail.com
16 */
17
18 package net.postgis.jdbc;
19
20
21 import net.postgis.tools.testutils.TestContainerController;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
24 import org.testng.Assert;
25 import org.testng.ITestContext;
26 import org.testng.annotations.AfterMethod;
27 import org.testng.annotations.BeforeMethod;
28 import org.testng.annotations.Test;
29
30 import java.sql.Connection;
31 import java.sql.DatabaseMetaData;
32 import java.sql.DriverManager;
33 import java.sql.PreparedStatement;
34 import java.sql.ResultSet;
35 import java.sql.Statement;
36 import java.util.UUID;
37
38
39 /**
40 * Integration tests for PGgeography.
41 *
42 * @author Phillip Ross
43 */
44 public class GeographyDatatypeTest {
45
46 /** The static logger instance. */
47 private static final Logger logger = LoggerFactory.getLogger(GeographyDatatypeTest.class);
48
49 /** The jdbc url prefix containing the jdbc protocol to be used for tests. */
50 private static final String JDBC_URL_PROTOCOL_PREFIX = "jdbc:postgresql";
51
52 /** The jdbc url prefix containing the jdbc lightweight protocol to be used for tests. */
53 private static final String JDBC_URL_LW_PROTOCOL_PREFIX = "jdbc:postgresql_lwgis";
54
55 /** The prefix for database tables used in the tests. */
56 private static final String DATABASE_TABLE_NAME_PREFIX = "jdbc_test";
57
58 /** Test geometries dataset. */
59 public static final String[] testGeometries = new String[] {
60 "POINT(10 10)", // 2D
61 "POINT(10 10 0)", // 3D with 3rd coordinate set to 0
62 "POINT(10 10 20)", // 3D
63 "POINT(1e100 1.2345e-100 -2e-5)", // 3D with scientific notation
64 "POINTM(10 10 20)", // 2D + Measures
65 "POINT(10 10 20 30)", // 3D + Measures
66 "MULTIPOINT(11 12, 20 20)", // broken format, see http://lists.jump-project.org/pipermail/jts-devel/2006-April/001572.html
67 "MULTIPOINT(11 12 13, 20 20 20)", // broken format
68 "MULTIPOINTM(11 12 13, 20 20 20)", // broken format
69 "MULTIPOINT(11 12 13 14,20 20 20 20)", // broken format
70 "MULTIPOINT((11 12), (20 20))", // OGC conforming format
71 "MULTIPOINT((11 12 13), (20 20 20))",
72 "MULTIPOINTM((11 12 13), (20 20 20))",
73 "MULTIPOINT((11 12 13 14),(20 20 20 20))",
74 "LINESTRING(10 10,20 20,50 50,34 34)",
75 "LINESTRING(10 10 20,20 20 20,50 50 50,34 34 34)",
76 "LINESTRINGM(10 10 20,20 20 20,50 50 50,34 34 34)",
77 "LINESTRING(10 10 20 20,20 20 20 20,50 50 50 50,34 34 34 50)",
78 "POLYGON((10 10,20 10,20 20,20 10,10 10),(5 5,5 6,6 6,6 5,5 5))",
79 "POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))",
80 "POLYGONM((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))",
81 "POLYGON((10 10 0 7,20 10 0 7,20 20 0 7,20 10 0 7,10 10 0 7),(5 5 0 7,5 6 0 7,6 6 0 7,6 5 0 7,5 5 0 7))",
82 "MULTIPOLYGON(((10 10,20 10,20 20,20 10,10 10),(5 5,5 6,6 6,6 5,5 5)),((10 10,20 10,20 20,20 10,10 10),(5 5,5 6,6 6,6 5,5 5)))",
83 "MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))",
84 "MULTIPOLYGONM(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))",
85 "MULTIPOLYGON(((10 10 0 7,20 10 0 7,20 20 0 7,20 10 0 7,10 10 0 7),(5 5 0 7,5 6 0 7,6 6 0 7,6 5 0 7,5 5 0 7)),((10 10 0 7,20 10 0 7,20 20 0 7,20 10 0 7,10 10 0 7),(5 5 0 7,5 6 0 7,6 6 0 7,6 5 0 7,5 5 0 7)))",
86 "MULTILINESTRING((10 10,20 10,20 20,20 10,10 10),(5 5,5 6,6 6,6 5,5 5))",
87 "MULTILINESTRING((10 10 5,20 10 5,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))",
88 "MULTILINESTRINGM((10 10 7,20 10 7,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))",
89 "MULTILINESTRING((10 10 0 7,20 10 0 7,20 20 0 7,20 10 0 7,10 10 0 7),(5 5 0 7,5 6 0 7,6 6 0 7,6 5 0 7,5 5 0 7))",
90 "GEOMETRYCOLLECTION(POINT(10 10),POINT(20 20))",
91 "GEOMETRYCOLLECTION(POINT(10 10 20),POINT(20 20 20))",
92 "GEOMETRYCOLLECTION(POINT(10 10 20 7),POINT(20 20 20 7))",
93 "GEOMETRYCOLLECTION(LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34),LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34))",
94 "GEOMETRYCOLLECTION(POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))",
95 "GEOMETRYCOLLECTION(MULTIPOINT(10 10 10, 20 20 20),MULTIPOINT(10 10 10, 20 20 20))", // Cannot be parsed by 0.X servers, broken format
96 "GEOMETRYCOLLECTION(MULTIPOINT((10 10 10), (20 20 20)),MULTIPOINT((10 10 10), (20 20 20)))", // Cannot be parsed by 0.X servers, OGC conformant
97 "GEOMETRYCOLLECTION(MULTILINESTRING((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))", // PostGIs 0.X "flattens" this geometry, so it is not equal after reparsing.
98 "GEOMETRYCOLLECTION(MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))),MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))))", // PostGIs 0.X "flattens" this geometry, so it is not equal after reparsing.
99 "GEOMETRYCOLLECTION(POINT(10 10 20),LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34),POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))",
100 "GEOMETRYCOLLECTION(POINT(10 10 20),MULTIPOINT(10 10 10, 20 20 20),LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34),POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))),MULTILINESTRING((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))", // Collections that contain both X and MultiX do not work on PostGIS 0.x, broken format
101 "GEOMETRYCOLLECTION(POINT(10 10 20),MULTIPOINT((10 10 10), (20 20 20)),LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34),POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))),MULTILINESTRING((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))", // Collections that contain both X and MultiX do not work on PostGIS 0.x, OGC conformant
102 "GEOMETRYCOLLECTION EMPTY", // new (correct) representation
103 "GEOMETRYCOLLECTIONM(POINTM(10 10 20),POINTM(20 20 20))"
104 };
105
106 /** The JDBC Connection to be used for tests. */
107 private Connection connection = null;
108
109 /** The JDBC Connection w/ lightweight protocol to be used for tests. */
110 private Connection connectionLW = null;
111
112
113 /**
114 * Initializes a new JDBC Connection.
115 *
116 * @param ctx the test context
117 * @throws Exception when an exception occurs
118 */
119 @BeforeMethod
120 public void initJdbcConnection(ITestContext ctx) throws Exception {
121 final String jdbcUrlSuffix = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_JDBC_URL_SUFFIX);
122 Assert.assertNotNull(jdbcUrlSuffix);
123 final String jdbcUrl = JDBC_URL_PROTOCOL_PREFIX + jdbcUrlSuffix;
124 final String jdbcUrlLW = JDBC_URL_LW_PROTOCOL_PREFIX + jdbcUrlSuffix;
125 final String jdbcUsername = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_USER_PARAM_NAME);
126 Assert.assertNotNull(jdbcUsername);
127 final String jdbcPassword = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_PW_PARAM_NAME);
128 Assert.assertNotNull(jdbcPassword);
129 Class.forName("net.postgis.jdbc.DriverWrapperLW");
130 connection = DriverManager.getConnection(jdbcUrl, jdbcUsername, jdbcPassword);
131 connectionLW = DriverManager.getConnection(jdbcUrlLW, jdbcUsername, jdbcPassword);
132 }
133
134
135 /**
136 * Un-allocates the JDBC connection.
137 *
138 * @throws Exception when an exception occurs
139 */
140 @AfterMethod
141 public void unallocateDatabaseResources() throws Exception {
142 if ((connection != null) && (!connection.isClosed())) {
143 connection.close();
144 }
145 if ((connectionLW != null) && (!connectionLW.isClosed())) {
146 connection.close();
147 }
148 }
149
150
151 /**
152 * Test inserting geometries into the database with prepared statements and querying back the results with
153 * both geometry/geography and standard/lightweight.
154 *
155 * @throws Exception when an exception occurs.
156 */
157 @Test
158 public void testDatatypes() throws Exception {
159
160 final String testTableName = DATABASE_TABLE_NAME_PREFIX
161 + "_"
162 + UUID.randomUUID()
163 .toString()
164 .replaceAll("-", "");
165
166 final String dropTableSQL = "drop table " + testTableName;
167
168 final String createTableSQL = "create table " + testTableName
169 + " ( _id numeric,"
170 + " geometry_value geometry, geometrylw_value geometry,"
171 + " geography_value geography, geographylw_value geography)";
172 final int idColumnIndex = 1;
173 final int geometryValueColumnIndex = 2;
174 final int geometrylwValueColumnIndex = 3;
175 final int geographyValueColumnIndex = 4;
176 final int geographylwValueColumnIndex = 5;
177
178 final String insertSQL = "insert into " + testTableName + " ( "
179 + "_id, geometry_value, geometrylw_value, "
180 + "geography_value, geographylw_value) "
181 + "values ( ?, ?, ?, ?, ? )";
182
183 boolean tableExists = false;
184 DatabaseMetaData databaseMetaData = connection.getMetaData();
185 try (
186 ResultSet resultSet = databaseMetaData.getTables(
187 null, null, testTableName.toLowerCase(), new String[] { "TABLE" }
188 )
189 ) {
190 while (resultSet.next()) {
191 tableExists = true;
192 }
193 }
194
195 if (tableExists) {
196 logger.debug("Dropping pre-existing test table...");
197 try (Statement statement = connection.createStatement()) {
198 statement.executeQuery(dropTableSQL);
199 }
200 }
201
202 logger.debug("Creating test table...");
203 try (Statement statement = connection.createStatement()) {
204 statement.execute(createTableSQL);
205 }
206
207
208 logger.debug("Inserting test geometries into table...");
209 try (PreparedStatement preparedStatement = connection.prepareStatement(insertSQL)) {
210 for (int i = 0; i < testGeometries.length; i++) {
211 PGgeometry geometry = new PGgeometry(testGeometries[i]);
212 PGgeometryLW geometryLW = new PGgeometryLW(testGeometries[i]);
213 PGgeography geography = new PGgeography(testGeometries[i]);
214 PGgeographyLW geographyLW = new PGgeographyLW(testGeometries[i]);
215
216 preparedStatement.setInt(idColumnIndex, i);
217 preparedStatement.setObject(geometryValueColumnIndex, geometry);
218 preparedStatement.setObject(geometrylwValueColumnIndex, geometryLW);
219 preparedStatement.setObject(geographyValueColumnIndex, geography);
220 preparedStatement.setObject(geographylwValueColumnIndex, geographyLW);
221 preparedStatement.executeUpdate();
222 }
223 }
224
225 logger.debug("Querying table with standard connection...");
226 try (
227 Statement statement = connection.createStatement();
228 ResultSet resultSet = statement.executeQuery(
229 "select _id, geometry_value, geometrylw_value, geography_value, geographylw_value from "
230 + testTableName
231 )
232 ) {
233 while (resultSet.next()) {
234 Assert.assertEquals(resultSet.getObject(geometryValueColumnIndex).getClass(), PGgeometry.class);
235 Assert.assertEquals(resultSet.getObject(geometrylwValueColumnIndex).getClass(), PGgeometry.class);
236 Assert.assertEquals(resultSet.getObject(geographyValueColumnIndex).getClass(), PGgeography.class);
237 Assert.assertEquals(resultSet.getObject(geographylwValueColumnIndex).getClass(), PGgeography.class);
238 }
239 }
240
241 logger.debug("Querying table with lightweight connection...");
242 try (
243 Statement statement = connectionLW.createStatement();
244 ResultSet resultSet = statement.executeQuery(
245 "select _id, geometry_value, geometrylw_value, geography_value, geographylw_value from "
246 + testTableName
247 )
248 ) {
249 while (resultSet.next()) {
250 Assert.assertEquals(resultSet.getObject(geometryValueColumnIndex).getClass(), PGgeometryLW.class);
251 Assert.assertEquals(resultSet.getObject(geometrylwValueColumnIndex).getClass(), PGgeometryLW.class);
252 Assert.assertEquals(resultSet.getObject(geographyValueColumnIndex).getClass(), PGgeographyLW.class);
253 Assert.assertEquals(resultSet.getObject(geographylwValueColumnIndex).getClass(), PGgeographyLW.class);
254 }
255 }
256 }
257
258
259 }
0 /*
1 * ParserTest.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - example and test classes
4 *
5 * (C) 2004 Paul Ramsey, pramsey@refractions.net
6 *
7 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
8 *
9 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 */
26
27 package net.postgis.jdbc;
28
29
30 import net.postgis.jdbc.geometry.Geometry;
31 import net.postgis.jdbc.geometry.GeometryBuilder;
32 import net.postgis.jdbc.geometry.binary.BinaryParser;
33 import net.postgis.jdbc.geometry.binary.BinaryWriter;
34 import net.postgis.jdbc.geometry.binary.ValueSetter;
35 import net.postgis.tools.testutils.TestContainerController;
36 import net.postgis.jdbc.geometry.util.VersionUtil;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39 import org.testng.Assert;
40 import org.testng.ITestContext;
41 import org.testng.annotations.AfterClass;
42 import org.testng.annotations.BeforeClass;
43 import org.testng.annotations.Test;
44
45 import java.sql.Connection;
46 import java.sql.DriverManager;
47 import java.sql.PreparedStatement;
48 import java.sql.ResultSet;
49 import java.sql.SQLException;
50 import java.sql.Statement;
51 import java.sql.Types;
52 import java.util.Objects;
53
54
55 public class ParserTest {
56
57 private static final Logger logger = LoggerFactory.getLogger(ParserTest.class);
58
59 private static final String DRIVER_WRAPPER_CLASS_NAME = "net.postgis.jdbc.DriverWrapper";
60
61 private static final String DRIVER_WRAPPER_AUTOPROBE_CLASS_NAME = "net.postgis.jdbc.DriverWrapperAutoprobe";
62
63 /** The srid we use for the srid tests */
64 public static final int SRID = 4326;
65
66 /** The string prefix we get for the srid tests */
67 public static final String SRIDPREFIX = "SRID=" + SRID + ";";
68
69 /**
70 * Our set of geometries to test.
71 */
72 public static final String ALL = "ALL";
73 public static final String ONLY10 = "ONLY10";
74 public static final String EQUAL10 = "EQUAL10";
75 public static final String[][] testset = new String[][]{
76 {
77 ALL, // 2D
78 "POINT(10 10)"},
79 {
80 ALL, // 3D with 3rd coordinate set to 0
81 "POINT(10 10 0)"},
82 {
83 ALL, // 3D
84 "POINT(10 10 20)"},
85 {
86 ALL, // 3D with scientific notation
87 "POINT(1e100 1.2345e-100 -2e-5)"},
88 {
89 ONLY10, // 2D + Measures
90 "POINTM(10 10 20)"},
91 {
92 ONLY10, // 3D + Measures
93 "POINT(10 10 20 30)"},
94 {
95 ALL, // broken format, see http://lists.jump-project.org/pipermail/jts-devel/2006-April/001572.html
96 "MULTIPOINT(11 12, 20 20)"},
97 {
98 ALL,// broken format
99 "MULTIPOINT(11 12 13, 20 20 20)"},
100 {
101 ONLY10,// broken format
102 "MULTIPOINTM(11 12 13, 20 20 20)"},
103 {
104 ONLY10,// broken format
105 "MULTIPOINT(11 12 13 14,20 20 20 20)"},
106 {
107 ALL, // OGC conforming format
108 "MULTIPOINT((11 12), (20 20))"},
109 {
110 ALL,
111 "MULTIPOINT((11 12 13), (20 20 20))"},
112 {
113 ONLY10,
114 "MULTIPOINTM((11 12 13), (20 20 20))"},
115 {
116 ONLY10,
117 "MULTIPOINT((11 12 13 14),(20 20 20 20))"},
118 {
119 ALL,
120 "LINESTRING(10 10,20 20,50 50,34 34)"},
121 {
122 ALL,
123 "LINESTRING(10 10 20,20 20 20,50 50 50,34 34 34)"},
124 {
125 ONLY10,
126 "LINESTRINGM(10 10 20,20 20 20,50 50 50,34 34 34)"},
127 {
128 ONLY10,
129 "LINESTRING(10 10 20 20,20 20 20 20,50 50 50 50,34 34 34 50)"},
130 {
131 ALL,
132 "POLYGON((10 10,20 10,20 20,20 10,10 10),(5 5,5 6,6 6,6 5,5 5))"},
133 {
134 ALL,
135 "POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))"},
136 {
137 ONLY10,
138 "POLYGONM((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))"},
139 {
140 ONLY10,
141 "POLYGON((10 10 0 7,20 10 0 7,20 20 0 7,20 10 0 7,10 10 0 7),(5 5 0 7,5 6 0 7,6 6 0 7,6 5 0 7,5 5 0 7))"},
142 {
143 ALL,
144 "MULTIPOLYGON(((10 10,20 10,20 20,20 10,10 10),(5 5,5 6,6 6,6 5,5 5)),((10 10,20 10,20 20,20 10,10 10),(5 5,5 6,6 6,6 5,5 5)))"},
145 {
146 ALL,
147 "MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))"},
148 {
149 ONLY10,
150 "MULTIPOLYGONM(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))"},
151 {
152 ONLY10,
153 "MULTIPOLYGON(((10 10 0 7,20 10 0 7,20 20 0 7,20 10 0 7,10 10 0 7),(5 5 0 7,5 6 0 7,6 6 0 7,6 5 0 7,5 5 0 7)),((10 10 0 7,20 10 0 7,20 20 0 7,20 10 0 7,10 10 0 7),(5 5 0 7,5 6 0 7,6 6 0 7,6 5 0 7,5 5 0 7)))"},
154 {
155 ALL,
156 "MULTILINESTRING((10 10,20 10,20 20,20 10,10 10),(5 5,5 6,6 6,6 5,5 5))"},
157 {
158 ALL,
159 "MULTILINESTRING((10 10 5,20 10 5,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))"},
160 {
161 ONLY10,
162 "MULTILINESTRINGM((10 10 7,20 10 7,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))"},
163 {
164 ONLY10,
165 "MULTILINESTRING((10 10 0 7,20 10 0 7,20 20 0 7,20 10 0 7,10 10 0 7),(5 5 0 7,5 6 0 7,6 6 0 7,6 5 0 7,5 5 0 7))"},
166 {
167 ALL,
168 "GEOMETRYCOLLECTION(POINT(10 10),POINT(20 20))"},
169 {
170 ALL,
171 "GEOMETRYCOLLECTION(POINT(10 10 20),POINT(20 20 20))"},
172 {
173 ONLY10,
174 "GEOMETRYCOLLECTION(POINT(10 10 20 7),POINT(20 20 20 7))"},
175 {
176 ALL,
177 "GEOMETRYCOLLECTION(LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34),LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34))"},
178 {
179 ALL,
180 "GEOMETRYCOLLECTION(POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))"},
181 {
182 ONLY10, // Cannot be parsed by 0.X servers, broken format
183 "GEOMETRYCOLLECTION(MULTIPOINT(10 10 10, 20 20 20),MULTIPOINT(10 10 10, 20 20 20))"},
184 {
185 ONLY10, // Cannot be parsed by 0.X servers, OGC conformant
186 "GEOMETRYCOLLECTION(MULTIPOINT((10 10 10), (20 20 20)),MULTIPOINT((10 10 10), (20 20 20)))"},
187 {
188 EQUAL10, // PostGIs 0.X "flattens" this geometry, so it is not
189 // equal after reparsing.
190 "GEOMETRYCOLLECTION(MULTILINESTRING((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))"},
191 {
192 EQUAL10,// PostGIs 0.X "flattens" this geometry, so it is not equal
193 // after reparsing.
194 "GEOMETRYCOLLECTION(MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))),MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))))"},
195 {
196 ALL,
197 "GEOMETRYCOLLECTION(POINT(10 10 20),LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34),POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))"},
198 {
199 ONLY10, // Collections that contain both X and MultiX do not work on
200 // PostGIS 0.x, broken format
201 "GEOMETRYCOLLECTION(POINT(10 10 20),MULTIPOINT(10 10 10, 20 20 20),LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34),POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))),MULTILINESTRING((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))"},
202 {
203 ONLY10, // Collections that contain both X and MultiX do not work on
204 // PostGIS 0.x, OGC conformant
205 "GEOMETRYCOLLECTION(POINT(10 10 20),MULTIPOINT((10 10 10), (20 20 20)),LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34),POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))),MULTILINESTRING((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))"},
206 {
207 ALL,// new (correct) representation
208 "GEOMETRYCOLLECTION EMPTY"},
209 {
210 ALL,
211 "GEOMETRYCOLLECTIONM(POINTM(10 10 20),POINTM(20 20 20))"},
212 // end
213 };
214
215 public static final String[][] testSetNonWorking = new String[][]{
216 {
217 ALL, // Old (bad) PostGIS 0.X Representation
218 "GEOMETRYCOLLECTION(EMPTY)"},
219 {
220 ONLY10,// new (correct) representation - does not work on 0.X
221 "POINT EMPTY"},
222 {
223 ONLY10,// new (correct) representation - does not work on 0.X
224 "LINESTRING EMPTY"},
225 {
226 ONLY10,// new (correct) representation - does not work on 0.X
227 "POLYGON EMPTY"},
228 {
229 ONLY10,// new (correct) representation - does not work on 0.X
230 "MULTIPOINT EMPTY"},
231 {
232 ONLY10,// new (correct) representation - does not work on 0.X
233 "MULTILINESTRING EMPTY"},
234 {
235 ONLY10,// new (correct) representation - does not work on 0.X
236 "MULTIPOLYGON EMPTY"}
237 };
238
239 private static BinaryParser binaryParser = new BinaryParser();
240
241 private static final BinaryWriter binaryWriter = new BinaryWriter();
242
243 private Connection connection = null;
244
245 private Statement statement = null;
246
247
248 @Test
249 public void testParser() throws Exception {
250 for (String[] aTestset : testset) {
251 test(aTestset[1], aTestset[0]);
252 test(SRIDPREFIX + aTestset[1], aTestset[0]);
253 }
254 }
255
256
257 public void test(String WKT, String flags) throws SQLException {
258 logger.debug("Original: {} ", WKT);
259 Geometry geom = GeometryBuilder.geomFromString(WKT);
260 String parsed = geom.toString();
261 logger.debug("Parsed: {}", parsed);
262 Geometry regeom = GeometryBuilder.geomFromString(parsed);
263 String reparsed = regeom.toString();
264 logger.debug("Re-Parsed: {}", reparsed);
265 Assert.assertEquals(geom, regeom, "Geometries are not equal");
266 Assert.assertEquals(reparsed, parsed, "Text Reps are not equal");
267
268 String hexNWKT = binaryWriter.writeHexed(regeom, ValueSetter.NDR.NUMBER);
269 logger.debug("NDRHex: {}", hexNWKT);
270 regeom = GeometryBuilder.geomFromString(hexNWKT);
271 logger.debug("ReNDRHex: {}", regeom);
272 Assert.assertEquals(geom, regeom, "Geometries are not equal");
273
274 String hexXWKT = binaryWriter.writeHexed(regeom, ValueSetter.XDR.NUMBER);
275 logger.debug("XDRHex: {}", hexXWKT);
276 regeom = GeometryBuilder.geomFromString(hexXWKT);
277 logger.debug("ReXDRHex: {}", regeom);
278 Assert.assertEquals(geom, regeom, "Geometries are not equal");
279
280 byte[] NWKT = binaryWriter.writeBinary(regeom, ValueSetter.NDR.NUMBER);
281 regeom = binaryParser.parse(NWKT);
282 logger.debug("NDR: {}", regeom);
283 Assert.assertEquals(geom, regeom, "Geometries are not equal");
284
285 byte[] XWKT = binaryWriter.writeBinary(regeom, ValueSetter.XDR.NUMBER);
286 regeom = binaryParser.parse(XWKT);
287 logger.debug("XDR: {}", regeom);
288 Assert.assertEquals(geom, regeom, "Geometries are not equal");
289
290 final String postGISVersionString = VersionUtil.retrievePostGISServerVersionString(connection);
291 logger.debug("postGISVersionString: {}", postGISVersionString);
292 final String postGISMajorVersion = VersionUtil.retrievePostGISServerMajorVersion(connection);
293 logger.debug("postGISMajorVersion: {}", postGISMajorVersion);
294 final String postGISMinorVersion = VersionUtil.retrievePostGISServerMinorVersion(connection);
295 logger.debug("postGISMinorVersion: {}", postGISMinorVersion);
296
297 int serverPostgisMajor = 0;
298 try {
299 serverPostgisMajor = Integer.parseInt(postGISMajorVersion);
300 } catch (NumberFormatException nfe) {
301 logger.error("Caught a number format exception attempting to parse PostGIS Server Major Version");
302 }
303
304 if ((Objects.equals(flags, ONLY10)) && serverPostgisMajor < 1) {
305 logger.info("PostGIS server too old, skipping test on database connection {}", connection.getCatalog());
306 } else {
307 logger.debug("Testing on connection {}", connection.getCatalog());
308
309 Geometry sqlGeom = viaSQL(WKT);
310 logger.debug("SQLin: {}", sqlGeom);
311 if (!geom.equals(sqlGeom)) {
312 logger.warn("Geometries after SQL are not equal");
313 if (Objects.equals(flags, EQUAL10) && serverPostgisMajor < 1) {
314 logger.info("This is expected with PostGIS {}.X", serverPostgisMajor);
315 } else {
316 Assert.fail();
317 }
318 }
319
320 Geometry sqlreGeom = viaSQL(parsed);
321 logger.debug("SQLout: {}", sqlreGeom);
322 if (!geom.equals(sqlreGeom)) {
323 logger.warn("Reparsed Geometries after SQL are not equal!");
324 if (Objects.equals(flags, EQUAL10) && serverPostgisMajor < 1) {
325 logger.info("This is expected with PostGIS {}.X", serverPostgisMajor);
326 } else {
327 Assert.fail();
328 }
329 }
330
331 sqlreGeom = viaPrepSQL(geom, connection);
332 logger.debug("Prepared: {}", sqlreGeom.toString());
333 if (!geom.equals(sqlreGeom)) {
334 logger.warn("Reparsed Geometries after prepared StatementSQL are not equal!");
335 if (Objects.equals(flags, EQUAL10) && serverPostgisMajor < 1) {
336 logger.info("This is expected with PostGIS {}.X", serverPostgisMajor);
337 } else {
338 Assert.fail();
339 }
340 }
341
342 /*
343 // Temporarily removing this check since it breaks between PostGIS v2.4.4 and PostGIS v2.5.0
344 // Tests performed via psql between mdillon/postgis:9.3 and mdillon/postgis:9.4 shows the breakage
345 // Test is also broken in mdillon/postgis:11-alpine
346 // In psql, the sql statement "SELECT ST_AsEWKT(geometry_in('POINT(1e100 1.2345e-100 -2e-5)'));" returns
347 // "POINT(1e+100 1.2345e-100 -2e-05)" with 9.3 and "POINT(1e+100 0 -0.00002)" with 9.4 and later
348
349 // asEWKT() function is not present on PostGIS 0.X, and the test
350 // is pointless as 0.X uses EWKT as canonical rep so the same
351 // functionality was already tested above.
352 if (serverPostgisMajor >= 1) {
353 sqlGeom = ewktViaSQL(WKT, statement);
354 logger.debug("asEWKT: {}", sqlGeom);
355 Assert.assertEquals(geom, sqlGeom);
356 }
357 */
358
359 // asEWKB() function is not present on PostGIS 0.X.
360 if (serverPostgisMajor >= 1) {
361 sqlGeom = ewkbViaSQL(WKT, statement);
362 logger.debug("asEWKB: {}", sqlGeom);
363 Assert.assertEquals(geom, sqlGeom);
364 }
365
366 // HexEWKB parsing is not present on PostGIS 0.X.
367 if (serverPostgisMajor >= 1) {
368 sqlGeom = viaSQL(hexNWKT);
369 logger.debug("hexNWKT: {}", sqlGeom);
370 Assert.assertEquals(geom, sqlGeom);
371 }
372
373 if (serverPostgisMajor >= 1) {
374 sqlGeom = viaSQL(hexXWKT);
375 logger.debug("hexXWKT: {}", sqlGeom);
376 Assert.assertEquals(geom, sqlGeom);
377 }
378
379 // Canonical binary input is not present before 1.0
380 if (serverPostgisMajor >= 1) {
381 sqlGeom = binaryViaSQL(NWKT, connection);
382 logger.debug("NWKT: {}", sqlGeom);
383 Assert.assertEquals(geom, sqlGeom);
384 }
385
386 if (serverPostgisMajor >= 1) {
387 sqlGeom = binaryViaSQL(XWKT, connection);
388 logger.debug("XWKT: {}", sqlGeom);
389 Assert.assertEquals(geom, sqlGeom);
390 }
391 }
392 }
393
394
395 /** Pass a geometry representation through the SQL server */
396 private Geometry viaSQL(String rep) throws SQLException {
397 logger.trace("Geometry viaSQL(String rep)");
398 logger.trace("[P] rep => {}", rep);
399 ResultSet resultSet = statement.executeQuery("SELECT geometry_in('" + rep + "')");
400 resultSet.next();
401 return ((PGgeometry) resultSet.getObject(1)).getGeometry();
402 }
403
404
405 /**
406 * Pass a geometry representation through the SQL server via prepared
407 * statement
408 */
409 private static Geometry viaPrepSQL(Geometry geom, Connection conn) throws SQLException {
410 PreparedStatement preparedStatement = conn.prepareStatement("SELECT ?::geometry");
411 PGgeometry wrapper = new PGgeometry(geom);
412 preparedStatement.setObject(1, wrapper, Types.OTHER);
413 ResultSet resultSet = preparedStatement.executeQuery();
414 resultSet.next();
415 PGgeometry resultwrapper = (PGgeometry)resultSet.getObject(1);
416 return resultwrapper.getGeometry();
417 }
418
419
420 /** Pass a geometry representation through the SQL server via EWKT */
421 private static Geometry ewktViaSQL(String rep, Statement stat) throws SQLException {
422 ResultSet resultSet = stat.executeQuery("SELECT ST_AsEWKT(geometry_in('" + rep + "'))");
423 resultSet.next();
424 String resrep = resultSet.getString(1);
425 return GeometryBuilder.geomFromString(resrep);
426 }
427
428
429 /** Pass a geometry representation through the SQL server via EWKB */
430 private static Geometry ewkbViaSQL(String rep, Statement stat) throws SQLException {
431 ResultSet resultSet = stat.executeQuery("SELECT ST_AsEWKB(geometry_in('" + rep + "'))");
432 resultSet.next();
433 byte[] resrep = resultSet.getBytes(1);
434 return binaryParser.parse(resrep);
435 }
436
437
438 /** Pass a EWKB geometry representation through the server */
439 private static Geometry binaryViaSQL(byte[] rep, Connection conn) throws SQLException {
440 PreparedStatement preparedStatement = conn.prepareStatement("SELECT ?::bytea::geometry");
441 preparedStatement.setBytes(1, rep);
442 ResultSet resultSet = preparedStatement.executeQuery();
443 resultSet.next();
444 PGgeometry resultwrapper = ((PGgeometry) resultSet.getObject(1));
445 return resultwrapper.getGeometry();
446 }
447
448
449 @BeforeClass
450 public void initJdbcConnection(ITestContext ctx) throws Exception {
451 final String jdbcUrlSuffix = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_JDBC_URL_SUFFIX);
452 Assert.assertNotNull(jdbcUrlSuffix);
453 final String jdbcUrl = "jdbc:postgresql" + jdbcUrlSuffix;
454 final String jdbcUsername = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_USER_PARAM_NAME);
455 Assert.assertNotNull(jdbcUsername);
456 final String jdbcPassword = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_PW_PARAM_NAME);
457 Assert.assertNotNull(jdbcPassword);
458 Class.forName(DRIVER_WRAPPER_CLASS_NAME);
459 Class.forName(DRIVER_WRAPPER_AUTOPROBE_CLASS_NAME);
460 connection = DriverManager.getConnection(jdbcUrl, jdbcUsername, jdbcPassword);
461 statement = connection.createStatement();
462 }
463
464
465 @AfterClass
466 public void unallocateDatabaseResources() throws Exception {
467 if ((statement != null) && (!statement.isClosed())) {
468 statement.close();
469 }
470 if ((connection != null) && (!connection.isClosed())) {
471 connection.close();
472 }
473 }
474
475
476 }
0 /*
1 * ServerTest.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - example and test classes
4 *
5 * (C) 2004 Paul Ramsey, pramsey@refractions.net
6 *
7 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
8 *
9 * (C) 2017 Phillip Ross, phillip.w.g.ross@gmail.com
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 */
26
27 package net.postgis.jdbc;
28
29
30 import org.testng.Assert;
31 import org.testng.annotations.Test;
32
33 import java.io.ByteArrayOutputStream;
34 import java.io.NotSerializableException;
35 import java.io.ObjectOutputStream;
36
37
38 public class SerializationTest {
39
40
41 @Test
42 public void serializationCheckPGgeometry() throws Exception {
43 try {
44 new ObjectOutputStream(new ByteArrayOutputStream())
45 .writeObject(new PGgeometry("MULTIPOLYGON(((1 1,1 2,2 1,1 1)))"));
46 }
47 catch (NotSerializableException ex) {
48 Assert.fail("serialization of PGgeometry failed: " + ex);
49 }
50 }
51
52
53 }
0 /*
1 * ServerTest.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - example and test classes
4 *
5 * (C) 2004 Paul Ramsey, pramsey@refractions.net
6 *
7 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
8 *
9 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 */
26
27 package net.postgis.jdbc;
28
29
30 import net.postgis.tools.testutils.TestContainerController;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33 import org.testng.Assert;
34 import org.testng.ITestContext;
35 import org.testng.annotations.AfterClass;
36 import org.testng.annotations.BeforeClass;
37 import org.testng.annotations.Test;
38
39 import java.sql.*;
40 import java.util.UUID;
41
42
43 public class ServerTest {
44
45 private static final Logger logger = LoggerFactory.getLogger(ServerTest.class);
46
47 private static final String JDBC_DRIVER_CLASS_NAME = "org.postgresql.Driver";
48
49 private static final String DATABASE_TABLE_NAME_PREFIX = "jdbc_test";
50
51 private Connection connection = null;
52
53 private Statement statement = null;
54
55
56 @Test
57 public void testServer() throws Exception {
58 String dbtable = DATABASE_TABLE_NAME_PREFIX + "_" + UUID.randomUUID().toString().replaceAll("-", "");
59
60 String dropSQL = "drop table " + dbtable;
61 String createSQL = "create table " + dbtable + " (geom geometry, id int4)";
62 String insertPointSQL = "insert into " + dbtable + " values ('POINT (10 10 10)',1)";
63 String insertPolygonSQL = "insert into " + dbtable + " values ('POLYGON ((0 0 0,0 10 0,10 10 0,10 0 0,0 0 0))',2)";
64
65 logger.debug("Adding geometric type entries...");
66 ((org.postgresql.PGConnection)connection).addDataType("geometry", PGgeometry.class);
67 ((org.postgresql.PGConnection)connection).addDataType("box3d", PGbox3d.class);
68
69 logger.debug("Creating table with geometric types...");
70 boolean tableExists = false;
71 DatabaseMetaData databaseMetaData = connection.getMetaData();
72 try (ResultSet resultSet = databaseMetaData.getTables(null, null, dbtable.toLowerCase(), new String[] {"TABLE"})) {
73 while (resultSet.next()) {
74 tableExists = true;
75 }
76 }
77 if (tableExists) {
78 statement.execute(dropSQL);
79 }
80 statement.execute(createSQL);
81
82 logger.debug("Inserting point...");
83 statement.execute(insertPointSQL);
84
85 logger.debug("Inserting polygon...");
86 statement.execute(insertPolygonSQL);
87
88 logger.debug("Querying table...");
89 ResultSet resultSet = statement.executeQuery("select ST_AsText(geom),id from " + dbtable);
90 while (resultSet.next()) {
91 Object obj = resultSet.getObject(1);
92 int id = resultSet.getInt(2);
93 logger.debug("Row {}: {}", id, obj.toString());
94 }
95
96 }
97
98
99 @BeforeClass
100 public void initJdbcConnection(ITestContext ctx) throws Exception {
101 final String jdbcUrlSuffix = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_JDBC_URL_SUFFIX);
102 Assert.assertNotNull(jdbcUrlSuffix);
103 final String jdbcUrl = "jdbc:postgresql" + jdbcUrlSuffix;
104 final String jdbcUsername = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_USER_PARAM_NAME);
105 Assert.assertNotNull(jdbcUsername);
106 final String jdbcPassword = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_PW_PARAM_NAME);
107 Assert.assertNotNull(jdbcPassword);
108 Class.forName(JDBC_DRIVER_CLASS_NAME);
109 connection = DriverManager.getConnection(jdbcUrl, jdbcUsername, jdbcPassword);
110 statement = connection.createStatement();
111 }
112
113
114 @AfterClass
115 public void unallocateDatabaseResources() throws Exception {
116 if ((statement != null) && (!statement.isClosed())) {
117 statement.close();
118 }
119 if ((connection != null) && (!connection.isClosed())) {
120 connection.close();
121 }
122 }
123
124
125 }
0 package net.postgis.jdbc;
1
2 import org.junit.Assert;
3 import org.junit.Test;
4
5 import java.sql.Driver;
6 import java.sql.DriverManager;
7 import java.sql.SQLException;
8
9 /**
10 * Tests to ensure that the drivers that are registered as services in META-INF/services/java.sql.Driver are resolved
11 * correctly.
12 */
13 public class ServiceTest {
14
15 @Test
16 public void testWrapperService() throws SQLException {
17 Driver driver = DriverManager.getDriver("jdbc:postgresql_postGIS:/");
18 Assert.assertEquals(DriverWrapper.class, driver.getClass());
19 }
20
21 @Test
22 public void testWrapperAutoprobeService() throws SQLException {
23 Driver driver = DriverManager.getDriver("jdbc:postgresql_autogis:/");
24 Assert.assertEquals(DriverWrapperAutoprobe.class, driver.getClass());
25 }
26
27 @Test
28 public void testWrapperLWService() throws SQLException {
29 Driver driver = DriverManager.getDriver("jdbc:postgresql_lwgis:/");
30 Assert.assertEquals(DriverWrapperLW.class, driver.getClass());
31 }
32
33 }
0 /*
1 * VersionPrinter.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - example and test classes
4 *
5 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
6 *
7 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24
25 package net.postgis.jdbc;
26
27
28 import net.postgis.tools.testutils.TestContainerController;
29 import org.postgresql.Driver;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32 import org.testng.Assert;
33 import org.testng.ITestContext;
34 import org.testng.annotations.AfterClass;
35 import org.testng.annotations.BeforeClass;
36 import org.testng.annotations.Test;
37
38 import java.sql.*;
39
40
41 /**
42 * Prints out as much version information as available.
43 */
44 public class VersionPrinter {
45
46 private static final Logger logger = LoggerFactory.getLogger(VersionPrinter.class);
47
48 private static final String JDBC_DRIVER_CLASS_NAME = "org.postgresql.Driver";
49
50 public static String[] POSTGIS_FUNCTIONS = {
51 "postgis_version",
52 "postgis_proj_version",
53 "postgis_scripts_installed",
54 "postgis_lib_version",
55 "postgis_scripts_released",
56 "postgis_uses_stats",
57 "postgis_geos_version",
58 "postgis_scripts_build_date",
59 "postgis_lib_build_date",
60 "postgis_full_version",
61 "postgis_gdal_version",
62 "postgis_libjson_version",
63 "postgis_libxml_version",
64 "postgis_raster_lib_version",
65 "postgis_svn_version"
66 };
67
68 private Connection connection = null;
69
70 private Statement statement = null;
71
72
73 @Test
74 public void test() throws Exception {
75
76 // Print PostGIS version
77 logger.info("*** PostGIS jdbc client code ***");
78 String fullVersion = Version.getFullVersion();
79 Assert.assertNotNull(fullVersion);
80 logger.info("\t getFullVersion: {}", fullVersion);
81
82 // Print PostgreSQL JDBC Versions
83 logger.info("*** PostgreSQL JDBC Driver ***");
84 String driverVersion = Driver.getVersion();
85 Assert.assertNotNull(driverVersion);
86 logger.info("\t getVersion: {}", driverVersion);
87
88 try {
89 Driver driver = new Driver();
90 int majorVersion = driver.getMajorVersion();
91 Assert.assertNotEquals(majorVersion, 0);
92 logger.info("\t getMajorVersion: {}", majorVersion);
93 int minorVersion = driver.getMinorVersion();
94 Assert.assertNotEquals(minorVersion, 0);
95 logger.info("\t getMinorVersion: {}", majorVersion);
96 } catch (Exception e) {
97 logger.error("Cannot create Driver instance: {}", e.getMessage());
98 }
99
100 // Print PostgreSQL server versions
101 Assert.assertNotNull(connection);
102 Statement statement = connection.createStatement();
103 if (statement == null) {
104 logger.info("No online version available.");
105 } else {
106 logger.info("*** PostgreSQL Server ***");
107 String versionString = getVersionString("version");
108 logger.debug("\t version: {}", versionString);
109
110 // Print PostGIS versions
111 logger.info("*** PostGIS Server ***");
112 for (String GISVERSION : POSTGIS_FUNCTIONS) {
113 versionString = getVersionString(GISVERSION);
114 logger.debug("\t {} version: {}", GISVERSION, versionString);
115 }
116 }
117 }
118
119
120 public String getVersionString(String function) throws SQLException {
121 String result = "-- unavailable -- ";
122 try {
123 ResultSet resultSet = statement.executeQuery("SELECT " + function + "()");
124 if (resultSet.next()) {
125 String version = resultSet.getString(1);
126 if (version != null) {
127 result = version.trim();
128 } else {
129 result = "-- null result --";
130 }
131 } else {
132 result = "-- no result --";
133 }
134 } catch (SQLException sqle) {
135 // If the function does not exist, a SQLException will be thrown, but it should be caught an swallowed if
136 // the "does not exist" string is in the error message. The SQLException might be thrown for some other
137 // problem not related to the missing function, so rethrow it if it doesn't contain the string.
138 if (!sqle.getMessage().contains("does not exist")) {
139 throw sqle;
140 }
141 }
142 return result;
143 }
144
145
146 @BeforeClass
147 public void initJdbcConnection(ITestContext ctx) throws Exception {
148 final String jdbcUrlSuffix = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_JDBC_URL_SUFFIX);
149 Assert.assertNotNull(jdbcUrlSuffix);
150 final String jdbcUrl = "jdbc:postgresql" + jdbcUrlSuffix;
151 final String jdbcUsername = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_USER_PARAM_NAME);
152 Assert.assertNotNull(jdbcUsername);
153 final String jdbcPassword = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_PW_PARAM_NAME);
154 Assert.assertNotNull(jdbcPassword);
155 Class.forName(JDBC_DRIVER_CLASS_NAME);
156 connection = DriverManager.getConnection(jdbcUrl, jdbcUsername, jdbcPassword);
157 statement = connection.createStatement();
158 }
159
160
161 @AfterClass
162 public void unallocateDatabaseResources() throws Exception {
163 if ((statement != null) && (!statement.isClosed())) {
164 statement.close();
165 }
166 if ((connection != null) && (!connection.isClosed())) {
167 connection.close();
168 }
169 }
170
171
172 }
0 /*
1 * This library is free software; you can redistribute it and/or
2 * modify it under the terms of the GNU Lesser General Public
3 * License as published by the Free Software Foundation; either
4 * version 2.1 of the License, or (at your option) any later version.
5 *
6 * This library is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 * Lesser General Public License for more details.
10 *
11 * You should have received a copy of the GNU Lesser General Public
12 * License along with this library; if not, write to the Free Software
13 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
14 *
15 * (C) 2018 Phillip Ross, phillip.w.g.ross@gmail.com
16 */
17
18 package net.postgis.jdbc.util;
19
20
21 import net.postgis.tools.testutils.TestContainerController;
22 import net.postgis.jdbc.geometry.util.VersionFunctions;
23 import net.postgis.jdbc.geometry.util.VersionUtil;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
26 import org.testng.Assert;
27 import org.testng.ITestContext;
28 import org.testng.annotations.AfterMethod;
29 import org.testng.annotations.BeforeMethod;
30 import org.testng.annotations.Test;
31
32 import java.sql.Connection;
33 import java.sql.DriverManager;
34 import java.sql.SQLException;
35 import java.util.StringTokenizer;
36
37
38 /**
39 * Integration tests for VersionUtil.
40 *
41 * @author Phillip Ross
42 */
43 public class VersionUtilIT {
44
45 /** The static logger instance. */
46 private static final Logger logger = LoggerFactory.getLogger(VersionUtilIT.class);
47
48 /** The jdbc url prefix containing the jdbc protocol to be used for tests. */
49 private static final String JDBC_URL_PROTOCOL_PREFIX = "jdbc:postgresql";
50
51 /** The JDBC Connection to be used for tests. */
52 private Connection connection = null;
53
54
55 /**
56 * Initializes a new JDBC Connection.
57 *
58 * @param ctx the test context
59 * @throws Exception when an exception occurs
60 */
61 @BeforeMethod
62 public void initJdbcConnection(ITestContext ctx) throws Exception {
63 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
64 final String jdbcUrlSuffix = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_JDBC_URL_SUFFIX);
65 Assert.assertNotNull(jdbcUrlSuffix);
66 final String jdbcUrl = JDBC_URL_PROTOCOL_PREFIX + jdbcUrlSuffix;
67 final String jdbcUsername = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_USER_PARAM_NAME);
68 Assert.assertNotNull(jdbcUsername);
69 final String jdbcPassword = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_PW_PARAM_NAME);
70 Assert.assertNotNull(jdbcPassword);
71 connection = DriverManager.getConnection(jdbcUrl, jdbcUsername, jdbcPassword);
72 }
73
74
75 /**
76 * Un-allocates the JDBC connection.
77 *
78 * @throws Exception when an exception occurs
79 */
80 @AfterMethod
81 public void unallocateDatabaseResources() throws Exception {
82 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
83 if ((connection != null) && (!connection.isClosed())) {
84 connection.close();
85 }
86 }
87
88
89 /**
90 * Test getting version string with a null connection.
91 *
92 * @throws Exception when an exception occurs
93 */
94 @Test(expectedExceptions = NullPointerException.class, expectedExceptionsMessageRegExp = ".*null connection.*")
95 public void test_VersionUtil_GetVersionString_NullConnection() throws Exception {
96 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
97 VersionUtil.getVersionString(null, VersionFunctions.POSTGIS_FULL_VERSION.toString());
98 }
99
100
101 /**
102 * Test getting version string with an invalid connection.
103 *
104 * @throws Exception when an exception occurs
105 */
106 @Test(expectedExceptions = SQLException.class, expectedExceptionsMessageRegExp = ".*connection.*not valid.*")
107 public void test_VersionUtil_GetVersionString_InvalidConnection() throws Exception {
108 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
109 connection.close();
110 VersionUtil.getVersionString(connection, VersionFunctions.POSTGIS_FULL_VERSION.toString());
111 }
112
113
114 /**
115 * Test getting version string with an invalid function name.
116 *
117 * @throws Exception when an exception occurs
118 */
119 @Test(
120 expectedExceptions = SQLException.class,
121 expectedExceptionsMessageRegExp = ".*(?!" + VersionUtil.NONEXISTENT_FUNCTION_ERROR_MESSAGE_CONTENT + ")"
122 )
123 public void test_VersionUtil_GetVersionString_InvalidFunctionName() throws Exception {
124 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
125 VersionUtil.getVersionString(connection, "invalid.function.name");
126 }
127
128
129 /**
130 * Test getting version string with a null function.
131 *
132 * @throws Exception when an exception occurs
133 */
134 @Test(expectedExceptions = NullPointerException.class, expectedExceptionsMessageRegExp = ".*null function.*")
135 public void test_VersionUtil_GetVersionString_NullFunction() throws Exception {
136 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
137 VersionUtil.getVersionString(connection, null);
138 }
139
140
141 /**
142 * Test getting version string of an unavailable function.
143 *
144 * @throws Exception when an exception occurs
145 */
146 @Test
147 public void test_VersionUtil_GetVersionString_Unavailable() throws Exception {
148 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
149 Assert.assertTrue(
150 VersionUtil.getVersionString(connection, "nonexistent")
151 .contains("unavailable")
152 );
153 }
154
155
156 /**
157 * Test getting version strings for all enumerated version functions.
158 *
159 * @throws Exception when an exception occurs
160 */
161 @Test
162 public void test_VersionUtil_GetVersionString_VersionFunctionsEnum() throws Exception {
163 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
164 for (int i = 0; i < VersionFunctions.values().length; i++) {
165 String function = VersionFunctions.values()[i].toString();
166 String version = VersionUtil.getVersionString(connection, function);
167 logger.debug("function [{}] => version string [{}]", function, version);
168 }
169 }
170
171
172 /**
173 * Test getting the server version string with a null connection.
174 *
175 * @throws Exception when an exception occurs
176 */
177 @Test(expectedExceptions = NullPointerException.class, expectedExceptionsMessageRegExp = ".*null connection.*")
178 public void test_VersionUtil_RetrievePostGISServerVersionString_NullConnection() throws Exception {
179 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
180 VersionUtil.retrievePostGISServerVersionString(null);
181 }
182
183
184 /**
185 * Test getting the server version string with an invalid connection.
186 *
187 * @throws Exception when an exception occurs
188 */
189 @Test(expectedExceptions = SQLException.class, expectedExceptionsMessageRegExp = ".*connection.*not valid.*")
190 public void test_VersionUtil_RetrievePostGISServerVersionString_InvalidConnection() throws Exception {
191 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
192 connection.close();
193 VersionUtil.retrievePostGISServerVersionString(connection);
194 }
195
196
197 /**
198 * Test getting the server version string.
199 *
200 * @throws Exception when an exception occurs
201 */
202 @Test
203 public void test_VersionUtil_RetrievePostGISServerVersionString() throws Exception {
204 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
205 String postGISServerVersionString = VersionUtil.retrievePostGISServerVersionString(connection);
206 Assert.assertNotNull(postGISServerVersionString);
207 logger.debug("PostGIS server version string [{}]", postGISServerVersionString);
208 }
209
210
211 /**
212 * Test getting the server version with a null connection.
213 *
214 * @throws Exception when an exception occurs
215 */
216 @Test(expectedExceptions = NullPointerException.class, expectedExceptionsMessageRegExp = ".*null connection.*")
217 public void test_VersionUtil_RetrievePostGISServerVersion_NullConnection() throws Exception {
218 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
219 VersionUtil.retrievePostGISServerVersion(null);
220 }
221
222
223 /**
224 * Test getting the server version with an invalid connection.
225 *
226 * @throws Exception when an exception occurs
227 */
228 @Test(expectedExceptions = SQLException.class, expectedExceptionsMessageRegExp = ".*connection.*not valid.*")
229 public void test_VersionUtil_RetrievePostGISServerVersion_InvalidConnection() throws Exception {
230 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
231 connection.close();
232 VersionUtil.retrievePostGISServerVersion(connection);
233 }
234
235
236 /**
237 * Test getting the server version.
238 *
239 * @throws Exception when an exception occurs
240 */
241 @Test
242 public void test_VersionUtil_RetrievePostGISServerVersion() throws Exception {
243 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
244 final String version = VersionUtil.retrievePostGISServerVersion(connection);
245 Assert.assertNotNull(version);
246 logger.debug("PostGIS server version [{}]", version);
247 }
248
249
250 /**
251 * Test getting the server major version with a null connection.
252 *
253 * @throws Exception when an exception occurs
254 */
255 @Test(expectedExceptions = NullPointerException.class, expectedExceptionsMessageRegExp = ".*null connection.*")
256 public void test_VersionUtil_RetrievePostGISServerMajorVersion_NullConnection() throws Exception {
257 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
258 VersionUtil.retrievePostGISServerMajorVersion(null);
259 }
260
261
262 /**
263 * Test getting the server major version with an invalid connection.
264 *
265 * @throws Exception when an exception occurs
266 */
267 @Test(expectedExceptions = SQLException.class, expectedExceptionsMessageRegExp = ".*connection.*not valid.*")
268 public void test_VersionUtil_RetrievePostGISServerMajorVersion_InvalidConnection() throws Exception {
269 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
270 connection.close();
271 VersionUtil.retrievePostGISServerMajorVersion(connection);
272 }
273
274
275 /**
276 * Test getting the server major version.
277 *
278 * @throws Exception when an exception occurs
279 */
280 @Test
281 public void test_VersionUtil_RetrievePostGISServerMajorVersion() throws Exception {
282 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
283 final String version = VersionUtil.retrievePostGISServerMajorVersion(connection);
284 Assert.assertNotNull(version);
285 logger.debug("PostGIS server major version [{}]", version);
286 }
287
288
289 /**
290 * Test getting the server minor version with a null connection.
291 *
292 * @throws Exception when an exception occurs
293 */
294 @Test(expectedExceptions = NullPointerException.class, expectedExceptionsMessageRegExp = ".*null connection.*")
295 public void test_VersionUtil_RetrievePostGISServerMinorVersion_NullConnection() throws Exception {
296 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
297 VersionUtil.retrievePostGISServerMinorVersion(null);
298 }
299
300
301 /**
302 * Test getting the server minor version with an invalid connection.
303 *
304 * @throws Exception when an exception occurs
305 */
306 @Test(expectedExceptions = SQLException.class, expectedExceptionsMessageRegExp = ".*connection.*not valid.*")
307 public void test_VersionUtil_RetrievePostGISServerMinorVersion_InvalidConnection() throws Exception {
308 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
309 connection.close();
310 VersionUtil.retrievePostGISServerMinorVersion(connection);
311 }
312
313
314 /**
315 * Test getting the server minor version.
316 *
317 * @throws Exception when an exception occurs
318 */
319 @Test
320 public void test_VersionUtil_RetrievePostGISServerMinorVersion() throws Exception {
321 logger.trace("[{}#{}]", getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
322 final String version = VersionUtil.retrievePostGISServerMinorVersion(connection);
323 Assert.assertNotNull(version);
324 logger.debug("PostGIS server minor version [{}]", version);
325 }
326
327
328 /**
329 * Test additional parsing assertions against retrieved versions.
330 *
331 * @throws Exception when an exception occurs
332 */
333 @Test
334 public void testServerVersionParsing() throws Exception {
335 logger.trace("[{}.{}]", getClass(), new Object(){}.getClass().getEnclosingMethod().getName());
336 final String versionString = VersionUtil.retrievePostGISServerVersionString(connection);
337 Assert.assertNotNull(versionString);
338 final String versionFull = VersionUtil.retrievePostGISServerVersion(connection);
339 Assert.assertNotNull(versionFull);
340 Assert.assertTrue(versionString.startsWith(versionFull));
341 final StringTokenizer stringTokenizer =
342 new StringTokenizer(versionString, VersionUtil.POSTGIS_SERVER_VERSION_SEPERATOR);
343 Assert.assertTrue(stringTokenizer.countTokens() > 0);
344 final String versionMajor = VersionUtil.retrievePostGISServerMajorVersion(connection);
345 Assert.assertEquals(versionMajor, stringTokenizer.nextToken());
346 if (stringTokenizer.countTokens() > 1) {
347 final String versionMinor = VersionUtil.retrievePostGISServerMinorVersion(connection);
348 Assert.assertEquals(versionMinor, stringTokenizer.nextToken());
349 }
350 }
351
352
353 }
0 <configuration debug="false">
1
2 <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
3 <layout class="ch.qos.logback.classic.PatternLayout">
4 <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
5 </layout>
6 </appender>
7
8 <root level="debug">
9 <appender-ref ref="STDOUT" />
10 </root>
11
12 <logger name="com.github.dockerjava" level="ERROR"/>
13 <logger name="org.testcontainers" level="ERROR"/>
14 <logger name="net.postgis" level="ERROR"/>
15
16 <logger name="net.postgis" level="ERROR"/>
17
18 </configuration>
0 <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
1 <suite name="Postgis JDBC Extensions Test Suite" verbose="1">
2
3 <test name="Postgis JDBC Tests">
4 <classes>
5 <class name="net.postgis.jdbc.DatatypesTest"/>
6 <class name="net.postgis.jdbc.SerializationTest"/>
7 </classes>
8 </test>
9
10 </suite>
0 <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
1 <suite name="Postgis JDBC Extensions Integration Test Suite" verbose="1">
2
3 <parameter name="test.container.image-name" value="${test.container.image}"/>
4 <parameter name="test.container.port" value="${test.db.port}"/>
5 <parameter name="test.container.env.user" value="${test.db.username}"/>
6 <parameter name="test.container.env.password" value="${test.db.password}"/>
7 <parameter name="test.container.env.db" value="${test.db.name}"/>
8
9 <test name="Postgis JDBC Integration Tests">
10 <classes>
11 <class name="net.postgis.tools.testutils.TestContainerController"/>
12 <class name="net.postgis.jdbc.util.VersionUtilIT"/>
13 <class name="net.postgis.jdbc.DatatypesAutoRegistrationTest"/>
14 <class name="net.postgis.jdbc.BoxesTest"/>
15 <class name="net.postgis.jdbc.EmptyGeometriesTest"/>
16 <class name="net.postgis.jdbc.GeographyDatatypeTest"/>
17 <class name="net.postgis.jdbc.ParserTest"/>
18 <class name="net.postgis.jdbc.ServerTest"/>
19 <class name="net.postgis.jdbc.VersionPrinter"/>
20 </classes>
21 </test>
22
23 </suite>
0 Todo for PostGIS 1.0 compatible JDBC classes
1
2 - even more Testing, especialy against different postgis,
3 pgjdbc and postgresql releases.
4
5 - Use JUnit for testing (maven)
6
7 - Unify the build of app java projects -> maven
8
9 - Handling of length() - esp. with modifying the geometries
10
11 - Handling of hashCode() - esp. with modifying the geometries
12
13 - Test correctness of toString() and getValue() for compatibility reasons
14
15 - See where the code can be cleaned and leaned.
16
17 - Finish JTS support
18
19 - Creating a sane extension interface for pgjdbc that allows binary
20 transfers and convince upstream to use it, then create support for it.
21
22 - Possibly adding server side code to support plJava
23 http://gborg.postgresql.org/project/pljava/projdisplay.php
24
25 - Rework the BinaryParser/BinaryWriter to work on SQLInput/SQLOutput
26 instances, as well as reworking ValueGetter/ValueSetter to implment those interfaces.
0 <?xml version="1.0" encoding="UTF-8"?>
1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
2 <modelVersion>4.0.0</modelVersion>
3
4 <parent>
5 <groupId>net.postgis</groupId>
6 <artifactId>postgis-java-aggregator</artifactId>
7 <version>2021.1.0</version>
8 </parent>
9
10 <artifactId>postgis-geometry</artifactId>
11 <version>2021.1.0</version>
12 <packaging>jar</packaging>
13
14 <name>PostGIS Geometry</name>
15 <description>Geometry classes provided by PostGIS JDBC Extension</description>
16
17 <properties />
18
19 <dependencies>
20 <dependency>
21 <groupId>net.postgis.tools</groupId>
22 <artifactId>test-utils</artifactId>
23 <version>2021.1.0</version>
24 <scope>test</scope>
25 </dependency>
26 </dependencies>
27
28 <build>
29 <plugins>
30 <plugin>
31 <artifactId>maven-jar-plugin</artifactId>
32 <configuration>
33 <archive>
34 <manifestEntries>
35 <Automatic-Module-Name>net.postgis.jdbc.geometry</Automatic-Module-Name>
36 </manifestEntries>
37 </archive>
38 </configuration>
39 </plugin>
40 </plugins>
41 </build>
42
43 </project>
0 module net.postgis.jdbc.geometry {
1 requires java.sql;
2
3 requires org.slf4j;
4
5 exports net.postgis.jdbc.geometry;
6 exports net.postgis.jdbc.geometry.binary;
7 exports net.postgis.jdbc.geometry.util;
8 }
0 /*
1 * ComposedGeom.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - geometry model
4 *
5 * (C) 2004 Paul Ramsey, pramsey@refractions.net
6 *
7 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
8 *
9 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 */
26
27 package net.postgis.jdbc.geometry;
28
29 import java.sql.SQLException;
30 import java.util.Iterator;
31 import java.util.List;
32
33 /**
34 * ComposedGeom - Abstract base class for all Geometries that are composed out
35 * of other Geometries.
36 *
37 * In fact, this currently are all Geometry subclasses except Point.
38 *
39 * @author markus.schaber@logix-tt.com
40 *
41 *
42 */
43 public abstract class ComposedGeom extends Geometry {
44 /* JDK 1.5 Serialization */
45 private static final long serialVersionUID = 0x100;
46
47 public static final Geometry[] EMPTY = new Geometry[0];
48
49 /**
50 * The Array containing the geometries
51 *
52 * This is only to be exposed by concrete subclasses, to retain type safety.
53 */
54 protected Geometry[] subgeoms = EMPTY;
55
56 /**
57 * Constructs an instance with the specified type
58 *
59 * @param type int value corresponding to the geometry type.
60 */
61 public ComposedGeom(int type) {
62 super(type);
63 }
64
65 public Geometry getSubGeometry(int index) {
66 return subgeoms[index];
67 }
68
69 public int numGeoms() {
70 return subgeoms.length;
71 }
72
73 protected ComposedGeom(int type, Geometry[] geoms) {
74 this(type);
75 this.subgeoms = geoms;
76 if (geoms.length > 0) {
77 dimension = geoms[0].dimension;
78 haveMeasure = geoms[0].haveMeasure;
79 } else {
80 dimension = 0;
81 }
82 }
83
84 protected ComposedGeom(int type, String value, boolean haveM) throws SQLException {
85 super(type);
86 value = initSRID(value);
87
88 String typestring = getTypeString();
89 if (value.indexOf(typestring) == 0) {
90 int pfxlen = typestring.length();
91 if (value.charAt(pfxlen) == 'M') {
92 pfxlen += 1;
93 haveM = true;
94 }
95 value = value.substring(pfxlen).trim();
96 } else if (value.charAt(0) != '(') {
97 // we are neigher inner nor outer rep.
98 throw new SQLException("Error parsing a " + typestring + " out of " + value);
99 }
100 if (value.equals("(EMPTY)")) {
101 // Special case for PostGIS 0.X style empty geometry collections
102 // (which are not OpenGIS compliant)
103 return;
104 }
105
106 String valueNoParans = GeometryTokenizer.removeLeadingAndTrailingStrings(value, "(", ")");
107 List<String> tokens = GeometryTokenizer.tokenize(valueNoParans, ',');
108
109 int subgeomcount = tokens.size();
110 subgeoms = createSubGeomArray(subgeomcount);
111 for (int p = 0; p < subgeomcount; p++) {
112 subgeoms[p] = createSubGeomInstance(tokens.get(p), haveM);
113 }
114 dimension = subgeoms[0].dimension;
115 // fetch haveMeasure from sub-point because haveM does only work with
116 // 2d+M, not with 3d+M geometries
117 haveMeasure = subgeoms[0].haveMeasure;
118 }
119
120 /**
121 * Return the appropriate instance of the sub-geometry - this encapsulates
122 * subclass specific constructor calls
123 *
124 * @param token The token containing the value for the sub-geometry
125 * @param haveM flag to indicate the existence of a measure
126 * @return the new sub-geometry
127 * @throws SQLException if a SQLException is thrown
128 */
129 protected abstract Geometry createSubGeomInstance(String token, boolean haveM) throws SQLException;
130
131 /**
132 * Return the appropriate instance of the sub-geometry array - this
133 * encapsulates subclass specific array instantiation
134 *
135 * @param size number of elements in the array
136 * @return Geometry array corresponding to the sub-geometry
137 */
138 protected abstract Geometry[] createSubGeomArray(int size);
139
140 protected boolean equalsintern(Geometry other) {
141 // Can be assumed to be the same subclass of Geometry, so it must be a
142 // ComposedGeom, too.
143 ComposedGeom cother = (ComposedGeom) other;
144
145 if (cother.subgeoms == null && subgeoms == null) {
146 return true;
147 } else if (cother.subgeoms == null || subgeoms == null) {
148 return false;
149 } else if (cother.subgeoms.length != subgeoms.length) {
150 return false;
151 } else if (subgeoms.length == 0) {
152 return true;
153 } else {
154 for (int i = 0; i < subgeoms.length; i++) {
155 if (!cother.subgeoms[i].equalsintern(this.subgeoms[i])) {
156 return false;
157 }
158 }
159 }
160 return true;
161 }
162
163 public int numPoints() {
164 if ((subgeoms == null) || (subgeoms.length == 0)) {
165 return 0;
166 } else {
167 int result = 0;
168 for (int i = 0; i < subgeoms.length; i++) {
169 result += subgeoms[i].numPoints();
170 }
171 return result;
172 }
173 }
174
175 public Point getPoint(int n) {
176 if (n < 0) {
177 throw new ArrayIndexOutOfBoundsException("Negative index not allowed");
178 } else if ((subgeoms == null) || (subgeoms.length == 0)) {
179 throw new ArrayIndexOutOfBoundsException("Empty Geometry has no Points!");
180 } else {
181 for (int i = 0; i < subgeoms.length; i++) {
182
183 Geometry current = subgeoms[i];
184 int np = current.numPoints();
185 if (n < np) {
186 return current.getPoint(n);
187 } else {
188 n -= np;
189 }
190 }
191 throw new ArrayIndexOutOfBoundsException("Index too large!");
192 }
193 }
194
195 /**
196 * Optimized version
197 */
198 public Point getLastPoint() {
199 if ((subgeoms == null) || (subgeoms.length == 0)) {
200 throw new ArrayIndexOutOfBoundsException("Empty Geometry has no Points!");
201 } else {
202 return subgeoms[subgeoms.length - 1].getLastPoint();
203 }
204 }
205
206 /**
207 * Optimized version
208 */
209 public Point getFirstPoint() {
210 if ((subgeoms == null) || (subgeoms.length == 0)) {
211 throw new ArrayIndexOutOfBoundsException("Empty Geometry has no Points!");
212 } else {
213 return subgeoms[0].getFirstPoint();
214 }
215 }
216
217 public Iterator iterator() {
218 return java.util.Arrays.asList(subgeoms).iterator();
219 }
220
221 public boolean isEmpty() {
222 return (subgeoms == null) || (subgeoms.length == 0);
223 }
224
225 protected void mediumWKT(StringBuffer sb) {
226 if ((subgeoms == null) || (subgeoms.length == 0)) {
227 sb.append(" EMPTY");
228 } else {
229 sb.append('(');
230 innerWKT(sb);
231 sb.append(')');
232 }
233 }
234
235 protected void innerWKT(StringBuffer sb) {
236 subgeoms[0].mediumWKT(sb);
237 for (int i = 1; i < subgeoms.length; i++) {
238 sb.append(',');
239 subgeoms[i].mediumWKT(sb);
240 }
241 }
242
243 // Hashing - still buggy!
244 boolean nohash = true;
245 int hashcode = 0;
246
247 public int hashCode() {
248 if (nohash) {
249 hashcode = super.hashCode() ^ subgeoms.hashCode();
250 nohash = false;
251 }
252 return hashcode;
253 }
254
255 public boolean checkConsistency() {
256 if (super.checkConsistency()) {
257 if (isEmpty()) {
258 return true;
259 }
260 // cache to avoid getMember opcode
261 int _dimension = this.dimension;
262 boolean _haveMeasure = this.haveMeasure;
263 int _srid = this.srid;
264 for (int i = 0; i < subgeoms.length; i++) {
265 Geometry sub = subgeoms[i];
266 if (!(sub.checkConsistency() && sub.dimension == _dimension
267 && sub.haveMeasure == _haveMeasure && sub.srid == _srid)) {
268 return false;
269 }
270 }
271 return true;
272 } else {
273 return false;
274 }
275 }
276
277 public void setSrid(int srid) {
278 super.setSrid(srid);
279 for (int i = 0; i < subgeoms.length; i++) {
280 subgeoms[i].setSrid(srid);
281 }
282 }
283 }
0 /*
1 * Geometry.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - geometry model
4 *
5 * (C) 2004 Paul Ramsey, pramsey@refractions.net
6 *
7 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
8 *
9 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 */
26
27 package net.postgis.jdbc.geometry;
28
29 import java.io.Serializable;
30
31 /** The base class of all geometries */
32 public abstract class Geometry implements Serializable {
33 /* JDK 1.5 Serialization */
34 private static final long serialVersionUID = 0x100;
35
36 // OpenGIS Geometry types as defined in the OGC WKB Spec
37 // (May we replace this with an ENUM as soon as JDK 1.5
38 // has gained widespread usage?)
39
40 /** Fake type for linear ring */
41 public static final int LINEARRING = 0;
42 /**
43 * The OGIS geometry type number for points.
44 */
45 public static final int POINT = 1;
46
47 /**
48 * The OGIS geometry type number for lines.
49 */
50 public static final int LINESTRING = 2;
51
52 /**
53 * The OGIS geometry type number for polygons.
54 */
55 public static final int POLYGON = 3;
56
57 /**
58 * The OGIS geometry type number for aggregate points.
59 */
60 public static final int MULTIPOINT = 4;
61
62 /**
63 * The OGIS geometry type number for aggregate lines.
64 */
65 public static final int MULTILINESTRING = 5;
66
67 /**
68 * The OGIS geometry type number for aggregate polygons.
69 */
70 public static final int MULTIPOLYGON = 6;
71
72 /**
73 * The OGIS geometry type number for feature collections.
74 */
75 public static final int GEOMETRYCOLLECTION = 7;
76
77 public static final String[] ALLTYPES = new String[] {
78 "", // internally used LinearRing does not have any text in front of
79 // it
80 "POINT", "LINESTRING", "POLYGON", "MULTIPOINT", "MULTILINESTRING",
81 "MULTIPOLYGON", "GEOMETRYCOLLECTION" };
82
83 /**
84 * The Text representations of the geometry types
85 *
86 * @param type int value of the type to lookup
87 * @return String reprentation of the type.
88 */
89 public static String getTypeString(int type) {
90 if (type >= 0 && type <= 7) {
91 return ALLTYPES[type];
92 } else {
93 throw new IllegalArgumentException("Unknown Geometry type" + type);
94 }
95 }
96
97 // Properties common to all geometries
98 /**
99 * The dimensionality of this feature (2,3)
100 */
101 public int dimension;
102
103 /**
104 * Do we have a measure (4th dimension)
105 */
106 public boolean haveMeasure = false;
107
108 /**
109 * The OGIS geometry type of this feature. this is final as it never
110 * changes, it is bound to the subclass of the instance.
111 */
112 public final int type;
113
114 /**
115 * Official UNKNOWN srid value
116 */
117 public final static int UNKNOWN_SRID = 0;
118
119 /**
120 * The spacial reference system id of this geometry, default is no srid
121 */
122 public int srid = UNKNOWN_SRID;
123
124 /**
125 * Parse a SRID value, anything {@code <= 0} is unknown
126 *
127 * @param srid the SRID to parse
128 * @return parsed SRID value
129 */
130 public static int parseSRID(int srid) {
131 if (srid < 0) {
132 /* TODO: raise a warning ? */
133 srid = 0;
134 }
135 return srid;
136 }
137
138 /**
139 * Constructor for subclasses
140 *
141 * @param type
142 * has to be given by all subclasses.
143 */
144 protected Geometry(int type) {
145 this.type = type;
146 }
147
148 /**
149 * java.lang.Object hashCode implementation
150 */
151 public int hashCode() {
152 return dimension | (type * 4) | (srid * 32);
153 }
154
155 /**
156 * java.lang.Object equals implementation
157 *
158 * @param other geometry to compare
159 * @return true if equal, false otherwise
160 */
161 public boolean equals(Object other) {
162 return (other != null) && (other instanceof Geometry)
163 && equals((Geometry) other);
164 }
165
166 /**
167 * geometry specific equals implementation - only defined for non-null
168 * values
169 *
170 * @param other geometry to compare
171 * @return true if equal, false otherwise
172 */
173 public boolean equals(Geometry other) {
174 return (other != null) && (this.dimension == other.dimension)
175 && (this.type == other.type) && (this.srid == other.srid)
176 && (this.haveMeasure == other.haveMeasure)
177 && other.getClass().equals(this.getClass())
178 && this.equalsintern(other);
179 }
180
181 /**
182 * Whether test coordinates for geometry - subclass specific code
183 *
184 * Implementors can assume that dimensin, type, srid and haveMeasure are
185 * equal, other != null and other is the same subclass.
186 *
187 * @param other geometry to compare
188 * @return true if equal, false otherwise
189 */
190 protected abstract boolean equalsintern(Geometry other);
191
192 /**
193 * Return the number of Points of the geometry
194 *
195 * @return number of points in the geometry
196 */
197 public abstract int numPoints();
198
199 /**
200 * Get the nth Point of the geometry
201 *
202 * @param n the index of the point, from 0 to numPoints()-1;
203 * @return nth point in the geometry
204 * @throws ArrayIndexOutOfBoundsException in case of an emtpy geometry or bad index.
205 */
206 public abstract Point getPoint(int n);
207
208 /**
209 * Same as getPoint(0);
210 *
211 * @return the initial Point in this geometry
212 */
213 public abstract Point getFirstPoint();
214
215 /**
216 * Same as getPoint(numPoints()-1);
217 *
218 * @return the final Point in this geometry
219 */
220 public abstract Point getLastPoint();
221
222 /**
223 * The OGIS geometry type number of this geometry.
224 *
225 * @return int value representation for the type of this geometry
226 */
227 public int getType() {
228 return this.type;
229 }
230
231 /**
232 * Return the Type as String
233 *
234 * @return String representation for the type of this geometry
235 */
236 public String getTypeString() {
237 return getTypeString(this.type);
238 }
239
240 /**
241 * Returns whether we have a measure
242 *
243 * @return true if the geometry has a measure, false otherwise
244 */
245 public boolean isMeasured() {
246 return haveMeasure;
247 }
248
249 /**
250 * Queries the number of geometric dimensions of this geometry. This does
251 * not include measures, as opposed to the server.
252 *
253 * @return The dimensionality (eg, 2D or 3D) of this geometry.
254 */
255 public int getDimension() {
256 return this.dimension;
257 }
258
259 /**
260 * The OGIS geometry type number of this geometry.
261 *
262 * @return the SRID of this geometry
263 */
264 public int getSrid() {
265 return this.srid;
266 }
267
268 /**
269 * Recursively sets the srid on this geometry and all contained
270 * subgeometries
271 *
272 * @param srid the SRID for this geometry
273 */
274 public void setSrid(int srid) {
275 this.srid = srid;
276 }
277
278 public String toString() {
279 StringBuffer sb = new StringBuffer();
280 if (srid != UNKNOWN_SRID) {
281 sb.append("SRID=");
282 sb.append(srid);
283 sb.append(';');
284 }
285 outerWKT(sb, true);
286 return sb.toString();
287 }
288
289 /**
290 * Render the WKT version of this Geometry (without SRID) into the given
291 * StringBuffer.
292 *
293 * @param sb StringBuffer to render into
294 * @param putM flag to indicate if the M character should be used.
295 */
296 public void outerWKT(StringBuffer sb, boolean putM) {
297 sb.append(getTypeString());
298 if (putM && haveMeasure && dimension == 2) {
299 sb.append('M');
300 }
301 mediumWKT(sb);
302 }
303
304 public final void outerWKT(StringBuffer sb) {
305 outerWKT(sb, true);
306 }
307
308 /**
309 * Render the WKT without the type name, but including the brackets into the
310 * StringBuffer
311 *
312 * @param sb StringBuffer to render into
313 */
314 protected void mediumWKT(StringBuffer sb) {
315 sb.append('(');
316 innerWKT(sb);
317 sb.append(')');
318 }
319
320 /**
321 * Render the "inner" part of the WKT (inside the brackets) into the
322 * StringBuffer.
323 *
324 * @param SB StringBuffer to render into
325 */
326 protected abstract void innerWKT(StringBuffer SB);
327
328 /**
329 * backwards compatibility method
330 *
331 * @return String representation of the value for the geometry.
332 */
333 public String getValue() {
334 StringBuffer sb = new StringBuffer();
335 mediumWKT(sb);
336 return sb.toString();
337 }
338
339 /**
340 * Do some internal consistency checks on the geometry.
341 *
342 * Currently, all Geometries must have a valid dimension (2 or 3) and a
343 * valid type. 2-dimensional Points must have Z=0.0, as well as non-measured
344 * Points must have m=0.0. Composed geometries must have all equal SRID,
345 * dimensionality and measures, as well as that they do not contain NULL or
346 * inconsistent subgeometries.
347 *
348 * BinaryParser and WKTParser should only generate consistent geometries.
349 * BinaryWriter may produce invalid results on inconsistent geometries.
350 *
351 * @return true if all checks are passed.
352 */
353 public boolean checkConsistency() {
354 return (dimension >= 2 && dimension <= 3) && (type >= 0 && type <= 7);
355 }
356
357 /**
358 * Splits the SRID=4711; part of a EWKT rep if present and sets the srid.
359 *
360 * @param value String value to extract the SRID from
361 * @return value without the SRID=4711; part
362 */
363 protected String initSRID(String value) {
364 value = value.trim();
365 if (value.startsWith("SRID=")) {
366 int index = value.indexOf(';', 5); // sridprefix length is 5
367 if (index == -1) {
368 throw new IllegalArgumentException(
369 "Error parsing Geometry - SRID not delimited with ';' ");
370 } else {
371 this.srid = Integer.parseInt(value.substring(5, index));
372 return value.substring(index + 1).trim();
373 }
374 } else {
375 return value;
376 }
377 }
378 }
0 package net.postgis.jdbc.geometry;
1
2
3 import net.postgis.jdbc.geometry.binary.BinaryParser;
4
5 import java.sql.SQLException;
6
7
8 /**
9 * Builds geometry instances.
10 *
11 * Note: This class contains the word "builder" but does NOT implement the builder pattern (yet).
12 *
13 * @author Phillip Ross
14 */
15 public class GeometryBuilder {
16
17 /** The prefix that indicates SRID presence */
18 public static final String SRIDPREFIX = "SRID=";
19
20
21 public static Geometry geomFromString(String value) throws SQLException {
22 return geomFromString(value, false);
23 }
24
25 public static Geometry geomFromString(String value, boolean haveM) throws SQLException {
26 BinaryParser bp = new BinaryParser();
27
28 return geomFromString(value, bp, haveM);
29 }
30
31 /**
32 * Maybe we could add more error checking here?
33 *
34 * @param value String representing the geometry
35 * @param bp BinaryParser to use whe parsing
36 * @return Geometry object parsed from the specified string value
37 * @throws SQLException when a SQLException occurs
38 */
39 public static Geometry geomFromString(String value, BinaryParser bp) throws SQLException {
40 return geomFromString(value, bp, false);
41 }
42
43 public static Geometry geomFromString(String value, BinaryParser bp, boolean haveM)
44 throws SQLException {
45 value = value.trim();
46
47 int srid = Geometry.UNKNOWN_SRID;
48
49 if (value.startsWith(SRIDPREFIX)) {
50 // break up geometry into srid and wkt
51 String[] parts = splitSRID(value);
52 value = parts[1].trim();
53 srid = Geometry.parseSRID(Integer.parseInt(parts[0].substring(5)));
54 }
55
56 Geometry result;
57 if (value.startsWith("00") || value.startsWith("01")) {
58 result = bp.parse(value);
59 } else if (value.endsWith("EMPTY")) {
60 // We have a standard conforming representation for an empty
61 // geometry which is to be parsed as an empty GeometryCollection.
62 result = new GeometryCollection();
63 } else if (value.startsWith("MULTIPOLYGON")) {
64 result = new MultiPolygon(value, haveM);
65 } else if (value.startsWith("MULTILINESTRING")) {
66 result = new MultiLineString(value, haveM);
67 } else if (value.startsWith("MULTIPOINT")) {
68 result = new MultiPoint(value, haveM);
69 } else if (value.startsWith("POLYGON")) {
70 result = new Polygon(value, haveM);
71 } else if (value.startsWith("LINESTRING")) {
72 result = new LineString(value, haveM);
73 } else if (value.startsWith("POINT")) {
74 result = new Point(value, haveM);
75 } else if (value.startsWith("GEOMETRYCOLLECTION")) {
76 result = new GeometryCollection(value, haveM);
77 } else {
78 throw new SQLException("Unknown type: " + value);
79 }
80
81 if (srid != Geometry.UNKNOWN_SRID) {
82 result.srid = srid;
83 }
84
85 return result;
86 }
87
88
89 /**
90 * Splits a String at the first occurrence of border character.
91 *
92 * Poor man's String.split() replacement, as String.split() was invented at
93 * jdk1.4, and the Debian PostGIS Maintainer had problems building the woody
94 * backport of his package using DFSG-free compilers. In all the cases we
95 * used split() in the net.postgis package, we only needed to split at the
96 * first occurence, and thus this code could even be faster.
97 *
98 * @param whole the String to be split
99 * @return String array containing the split elements
100 * @throws SQLException when a SQLException occurrs
101 */
102 public static String[] splitSRID(String whole) throws SQLException {
103 int index = whole.indexOf(';', 5); // sridprefix length is 5
104 if (index == -1) {
105 throw new SQLException("Error parsing Geometry - SRID not delimited with ';' ");
106 } else {
107 return new String[]{
108 whole.substring(0, index),
109 whole.substring(index + 1)};
110 }
111 }
112
113
114 }
0 /*
1 * GeometryCollection.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - geometry model
4 *
5 * (C) 2004 Paul Ramsey, pramsey@refractions.net
6 *
7 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
8 *
9 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 */
26
27 package net.postgis.jdbc.geometry;
28
29 import java.sql.SQLException;
30
31
32 /**
33 * Geometry Collection class WARNING: Currently only implements empty
34 * collections
35 *
36 * @author markus.schaber@logix-tt.com
37 *
38 */
39
40 public class GeometryCollection extends ComposedGeom {
41 /* JDK 1.5 Serialization */
42 private static final long serialVersionUID = 0x100;
43
44 public static final String GeoCollID = "GEOMETRYCOLLECTION";
45
46 public GeometryCollection() {
47 super(GEOMETRYCOLLECTION);
48 }
49
50 public GeometryCollection(Geometry[] geoms) {
51 super(GEOMETRYCOLLECTION, geoms);
52 }
53
54 public GeometryCollection(String value) throws SQLException {
55 this(value, false);
56 }
57
58 public GeometryCollection(String value, boolean haveM) throws SQLException {
59 super(GEOMETRYCOLLECTION, value, haveM);
60 }
61
62 protected Geometry[] createSubGeomArray(int ngeoms) {
63 return new Geometry[ngeoms];
64 }
65
66 protected Geometry createSubGeomInstance(String token, boolean haveM) throws SQLException {
67 return GeometryBuilder.geomFromString(token, haveM);
68 }
69
70 protected void innerWKT(StringBuffer SB) {
71 subgeoms[0].outerWKT(SB, true);
72 for (int i = 1; i < subgeoms.length; i++) {
73 SB.append(',');
74 subgeoms[i].outerWKT(SB, true);
75 }
76 }
77
78 public Geometry[] getGeometries() {
79 return subgeoms;
80 }
81 }
0 /*
1 * GeometryTokenizer.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - geometry model
4 *
5 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 *
21 */
22
23 package net.postgis.jdbc.geometry;
24
25
26 import java.util.ArrayList;
27 import java.util.List;
28 import java.util.Stack;
29
30
31 public class GeometryTokenizer {
32
33
34 public static List<String> tokenize(String string, char delimiter) {
35 List<String> tokens = new ArrayList<>();
36 Stack<Character> stack = new Stack<>();
37 int consumed = 0;
38 for (int position = 0; position < string.length(); position++) {
39 char character = string.charAt(position);
40 if ((character == '(') || (character == '[')) {
41 stack.push(character);
42 } else if (((character == ')') && (stack.peek() == '(')) ||
43 ((character == ']') && (stack.peek() == '['))
44 ) {
45 stack.pop();
46 }
47 if ((character == delimiter) && (stack.size() == 0)) {
48 tokens.add(string.substring(consumed, position));
49 consumed = position + 1;
50 }
51 }
52 if (consumed < string.length()) {
53 tokens.add(string.substring(consumed));
54 }
55 return tokens;
56 }
57
58
59 public static String removeLeadingAndTrailingStrings(String string, String leadingString, String trailingString) {
60 int startIndex = string.indexOf(leadingString);
61 if (startIndex == -1) {
62 startIndex = 0;
63 } else {
64 startIndex += leadingString.length();
65 }
66
67 int endIndex = string.lastIndexOf(trailingString);
68 if (endIndex == -1) {
69 endIndex = string.length();
70 }
71 return string.substring(startIndex, endIndex);
72 }
73
74
75 }
0 /*
1 * LineString.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - geometry model
4 *
5 * (C) 2004 Paul Ramsey, pramsey@refractions.net
6 *
7 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
8 *
9 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 */
26
27 package net.postgis.jdbc.geometry;
28
29 import java.sql.SQLException;
30
31 public class LineString extends PointComposedGeom {
32 /* JDK 1.5 Serialization */
33 private static final long serialVersionUID = 0x100;
34
35 double len = -1.;
36
37 public LineString() {
38 super(LINESTRING);
39 }
40
41 public LineString(Point[] points) {
42 super(LINESTRING, points);
43 }
44
45 public LineString(String value) throws SQLException {
46 super(LINESTRING, value);
47 }
48
49 public LineString(String value, boolean haveM) throws SQLException {
50 super(LINESTRING, value, haveM);
51 }
52
53 public LineString reverse() {
54 Point[] points = this.getPoints();
55 int l = points.length;
56 int i, j;
57 Point[] p = new Point[l];
58 for (i = 0, j = l - 1; i < l; i++, j--) {
59 p[i] = points[j];
60 }
61 return new LineString(p);
62 }
63
64 public LineString concat(LineString other) {
65 Point[] points = this.getPoints();
66 Point[] opoints = other.getPoints();
67
68 boolean cutPoint = this.getLastPoint() == null
69 || this.getLastPoint().equals(other.getFirstPoint());
70 int count = points.length + opoints.length - (cutPoint ? 1 : 0);
71 Point[] p = new Point[count];
72
73 // Maybe we should use System.arrayCopy here?
74 int i, j;
75 for (i = 0; i < points.length; i++) {
76 p[i] = points[i];
77 }
78 if (!cutPoint) {
79 p[i++] = other.getFirstPoint();
80 }
81 for (j = 1; j < opoints.length; j++, i++) {
82 p[i] = opoints[j];
83 }
84 return new LineString(p);
85 }
86
87 public double length() {
88 if (len < 0) {
89 Point[] points = this.getPoints();
90 if ((points == null) || (points.length < 2)) {
91 len = 0;
92 } else {
93 double sum = 0;
94 for (int i = 1; i < points.length; i++) {
95 sum += points[i - 1].distance(points[i]);
96 }
97 len = sum;
98 }
99 }
100 return len;
101 }
102 }
0 /*
1 * LinearRing.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - geometry model
4 *
5 * (C) 2004 Paul Ramsey, pramsey@refractions.net
6 *
7 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
8 *
9 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 */
26
27 package net.postgis.jdbc.geometry;
28
29 import java.sql.SQLException;
30 import java.util.List;
31
32
33 /**
34 * This represents the LinearRing GIS datatype. This type is used to construct
35 * the polygon types, but is not stored or retrieved directly from the database.
36 */
37 public class LinearRing extends PointComposedGeom {
38 /* JDK 1.5 Serialization */
39 private static final long serialVersionUID = 0x100;
40
41 public LinearRing(Point[] points) {
42 super(LINEARRING, points);
43 }
44
45 /**
46 * This is called to construct a LinearRing from the PostGIS string
47 * representation of a ring.
48 *
49 * @param value Definition of this ring in the PostGIS string format.
50 * @throws SQLException when a SQLException occurs
51 */
52 public LinearRing(String value) throws SQLException {
53 this(value, false);
54 }
55
56 /**
57 * @param value The text representation of this LinearRing
58 * @param haveM Hint whether we have a measure. This is given to us by other
59 * "parent" Polygon, and is passed further to our parent.
60 * @throws SQLException when a SQLException occurs
61 */
62
63 protected LinearRing(String value, boolean haveM) throws SQLException {
64 super(LINEARRING);
65 String valueNoParans = GeometryTokenizer.removeLeadingAndTrailingStrings(value.trim(), "(", ")");
66 List<String> tokens = GeometryTokenizer.tokenize(valueNoParans, ',');
67 int npoints = tokens.size();
68 Point[] points = new Point[npoints];
69 for (int p = 0; p < npoints; p++) {
70 points[p] = new Point(tokens.get(p), haveM);
71 }
72 this.dimension = points[0].dimension;
73 // fetch haveMeasure from subpoint because haveM does only work with
74 // 2d+M, not with 3d+M geometries
75 this.haveMeasure = points[0].haveMeasure;
76 this.subgeoms = points;
77 }
78
79 }
0 /*
1 * MultiLineString.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - geometry model
4 *
5 * (C) 2004 Paul Ramsey, pramsey@refractions.net
6 *
7 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
8 *
9 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 */
26
27 package net.postgis.jdbc.geometry;
28
29 import java.sql.SQLException;
30
31 public class MultiLineString extends ComposedGeom {
32 /* JDK 1.5 Serialization */
33 private static final long serialVersionUID = 0x100;
34
35 double len = -1;
36
37 public int hashCode() {
38 return super.hashCode() ^ (int) this.length();
39 }
40
41 public MultiLineString() {
42 super(MULTILINESTRING);
43 }
44
45 public MultiLineString(LineString[] lines) {
46 super(MULTILINESTRING, lines);
47 }
48
49 public MultiLineString(String value) throws SQLException {
50 this(value, false);
51 }
52
53 public MultiLineString(String value, boolean haveM) throws SQLException {
54 super(MULTILINESTRING, value, haveM);
55 }
56
57 protected Geometry createSubGeomInstance(String token, boolean haveM) throws SQLException {
58 return new LineString(token, haveM);
59 }
60
61 protected Geometry[] createSubGeomArray(int nlines) {
62 return new LineString[nlines];
63 }
64
65 public int numLines() {
66 return subgeoms.length;
67 }
68
69 public LineString[] getLines() {
70 return (LineString[]) subgeoms.clone();
71 }
72
73 public LineString getLine(int idx) {
74 if (idx >= 0 & idx < subgeoms.length) {
75 return (LineString) subgeoms[idx];
76 } else {
77 return null;
78 }
79 }
80
81 public double length() {
82 if (len < 0) {
83 LineString[] lines = (LineString[]) subgeoms;
84 if (lines.length < 1) {
85 len = 0;
86 } else {
87 double sum = 0;
88 for (int i = 0; i < lines.length; i++) {
89 sum += lines[i].length();
90 }
91 len = sum;
92 }
93 }
94 return len;
95 }
96 }
0 /*
1 * MultiPoint.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - geometry model
4 *
5 * (C) 2004 Paul Ramsey, pramsey@refractions.net
6 *
7 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
8 *
9 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 */
26
27 package net.postgis.jdbc.geometry;
28
29 import java.sql.SQLException;
30
31 public class MultiPoint extends PointComposedGeom {
32 /* JDK 1.5 Serialization */
33 private static final long serialVersionUID = 0x100;
34
35 public MultiPoint() {
36 super(MULTIPOINT);
37 }
38
39 public MultiPoint(Point[] points) {
40 super(MULTIPOINT, points);
41 }
42
43 public MultiPoint(String value) throws SQLException {
44 this(value, false);
45 }
46
47 protected MultiPoint(String value, boolean haveM) throws SQLException {
48 super(MULTIPOINT, value, haveM);
49 }
50 }
0 /*
1 * MultiPolygon.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - geometry model
4 *
5 * (C) 2004 Paul Ramsey, pramsey@refractions.net
6 *
7 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
8 *
9 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 */
26
27 package net.postgis.jdbc.geometry;
28
29 import java.sql.SQLException;
30
31 public class MultiPolygon extends ComposedGeom {
32 /* JDK 1.5 Serialization */
33 private static final long serialVersionUID = 0x100;
34
35 public MultiPolygon() {
36 super(MULTIPOLYGON);
37 }
38
39 public MultiPolygon(Polygon[] polygons) {
40 super(MULTIPOLYGON, polygons);
41 }
42
43 public MultiPolygon(String value) throws SQLException {
44 this(value, false);
45 }
46
47 protected MultiPolygon(String value, boolean haveM) throws SQLException {
48 super(MULTIPOLYGON, value, haveM);
49 }
50
51 protected Geometry[] createSubGeomArray(int npolygons) {
52 return new Polygon[npolygons];
53 }
54
55 protected Geometry createSubGeomInstance(String token, boolean haveM) throws SQLException {
56 return new Polygon(token, haveM);
57 }
58
59 public int numPolygons() {
60 return subgeoms.length;
61 }
62
63 public Polygon getPolygon(int idx) {
64 if (idx >= 0 & idx < subgeoms.length) {
65 return (Polygon) subgeoms[idx];
66 } else {
67 return null;
68 }
69 }
70
71 public Polygon[] getPolygons() {
72 return (Polygon[]) subgeoms;
73 }
74 }
0 /*
1 * Point.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - geometry model
4 *
5 * (C) 2004 Paul Ramsey, pramsey@refractions.net
6 *
7 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
8 *
9 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 */
26
27 package net.postgis.jdbc.geometry;
28
29 import java.sql.SQLException;
30 import java.util.List;
31
32 public class Point extends Geometry {
33 /* JDK 1.5 Serialization */
34 private static final long serialVersionUID = 0x100;
35
36 public static final boolean CUTINTS = true;
37
38 public int hashCode() {
39 return super.hashCode() ^ hashCode(x) ^ hashCode(y) ^ hashCode(z) ^ hashCode(m);
40 }
41
42 public static int hashCode(double value) {
43 long v = Double.doubleToLongBits(value);
44 return (int) (v ^ (v >>> 32));
45 }
46
47 protected boolean equalsintern(Geometry otherg) {
48 Point other = (Point) otherg;
49 return equals(other);
50 }
51
52 public static boolean double_equals(double a, double b) {
53 if ( Double.isNaN(a) && Double.isNaN(b) ) {
54 return true;
55 }
56 else {
57 return (a == b);
58 }
59 }
60
61 public final boolean equals(Point other) {
62 boolean xequals = double_equals(x, other.x);
63 boolean yequals = double_equals(y, other.y);
64 boolean zequals = ((dimension == 2) || double_equals(z, other.z));
65 boolean mequals = ((haveMeasure == false) || double_equals(m,other.m));
66 boolean result = xequals && yequals && zequals && mequals;
67 return result;
68 }
69
70 public Point getPoint(int index) {
71 if (index == 0) {
72 return this;
73 } else {
74 throw new ArrayIndexOutOfBoundsException("Point only has a single Point! " + index);
75 }
76 }
77
78 /** Optimized versions for this special case */
79 public Point getFirstPoint() {
80 return this;
81 }
82
83 /** Optimized versions for this special case */
84 public Point getLastPoint() {
85 return this;
86 }
87
88 public int numPoints() {
89 return 1;
90 }
91
92 /**
93 * The X coordinate of the point.
94 * In most long/lat systems, this is the longitude.
95 */
96 public double x;
97
98 /**
99 * The Y coordinate of the point.
100 * In most long/lat systems, this is the latitude.
101 */
102 public double y;
103
104 /**
105 * The Z coordinate of the point.
106 * In most long/lat systems, this is a radius from the
107 * center of the earth, or the height / elevation over
108 * the ground.
109 */
110 public double z;
111
112 /**
113 * The measure of the point.
114 */
115 public double m = 0.0;
116
117 public Point() {
118 super(POINT);
119 }
120
121 /** Constructs a new Point
122 * @param x the longitude / x ordinate
123 * @param y the latitude / y ordinate
124 * @param z the radius / height / elevation / z ordinate
125 */
126 public Point(double x, double y, double z) {
127 this();
128 this.x = x;
129 this.y = y;
130 this.z = z;
131 dimension = 3;
132 }
133
134 /** Constructs a new Point
135 * @param x the longitude / x ordinate
136 * @param y the latitude / y ordinate
137 */
138 public Point(double x, double y) {
139 this();
140 this.x = x;
141 this.y = y;
142 this.z = 0.0;
143 dimension = 2;
144 }
145
146 /**
147 * Construct a Point from EWKT.
148 *
149 * (3D and measures are legal, but SRID is not allowed).
150 *
151 * @param value String representation of the geometry.
152 * @throws SQLException when a SQLException occurs
153 */
154 public Point(String value) throws SQLException {
155 this(value, false);
156 }
157
158 /**
159 * Construct a Point
160 *
161 * @param value The text representation of this point
162 * @param haveM Hint whether we have a measure. This is used by other
163 * geometries parsing inner points where we only get "1 2 3 4"
164 * like strings without the "POINT(" and ")" stuff. If there
165 * acutally is a POINTM prefix, this overrides the given value.
166 * However, POINT does not set it to false, as they can be
167 * contained in measured collections, as in
168 * "GEOMETRYCOLLECTIONM(POINT(0 0 0))".
169 * @throws SQLException when a SQLException occurs
170 */
171 protected Point(String value, boolean haveM) throws SQLException {
172 this();
173 value = initSRID(value);
174
175 if (value.indexOf("POINTM") == 0) {
176 haveM = true;
177 value = value.substring(6).trim();
178 } else if (value.indexOf("POINT") == 0) {
179 value = value.substring(5).trim();
180 }
181 String valueNoParans = GeometryTokenizer.removeLeadingAndTrailingStrings(value, "(", ")");
182 List<String> tokens = GeometryTokenizer.tokenize(valueNoParans, ' ');
183 try {
184 x = Double.valueOf(tokens.get(0)).doubleValue();
185 y = Double.valueOf(tokens.get(1)).doubleValue();
186 haveM |= tokens.size() == 4;
187 if ((tokens.size() == 3 && !haveM) || (tokens.size() == 4)) {
188 z = Double.valueOf(tokens.get(2)).doubleValue();
189 dimension = 3;
190 } else {
191 dimension = 2;
192 }
193 if (haveM) {
194 m = Double.valueOf(tokens.get(dimension)).doubleValue();
195 }
196 } catch (NumberFormatException e) {
197 throw new SQLException("Error parsing Point: " + e.toString());
198 }
199 haveMeasure = haveM;
200 }
201
202 public void innerWKT(StringBuffer sb) {
203 sb.append(x);
204 if (CUTINTS)
205 cutint(sb);
206 sb.append(' ');
207 sb.append(y);
208 if (CUTINTS)
209 cutint(sb);
210 if (dimension == 3) {
211 sb.append(' ');
212 sb.append(z);
213 if (CUTINTS)
214 cutint(sb);
215 }
216 if (haveMeasure) {
217 sb.append(' ');
218 sb.append(m);
219 if (CUTINTS)
220 cutint(sb);
221 }
222 }
223
224 private static void cutint(StringBuffer sb) {
225 int l = sb.length() - 2;
226 if ((sb.charAt(l + 1) == '0') && (sb.charAt(l) == '.')) {
227 sb.setLength(l);
228 }
229 }
230
231 public double getX() {
232 return x;
233 }
234
235 public double getY() {
236 return y;
237 }
238
239 public double getZ() {
240 return z;
241 }
242
243 public double getM() {
244 return m;
245 }
246
247 public void setX(double x) {
248 this.x = x;
249 }
250
251 public void setY(double y) {
252 this.y = y;
253 }
254
255 public void setZ(double z) {
256 this.z = z;
257 }
258
259 public void setM(double m) {
260 haveMeasure = true;
261 this.m = m;
262 }
263
264 public void setX(int x) {
265 this.x = x;
266 }
267
268 public void setY(int y) {
269 this.y = y;
270 }
271
272 public void setZ(int z) {
273 this.z = z;
274 }
275
276 public double distance(Point other) {
277 double tx, ty, tz;
278 if (this.dimension != other.dimension) {
279 throw new IllegalArgumentException("Points have different dimensions!");
280 }
281 tx = this.x - other.x;
282 switch (this.dimension) {
283 case 1 :
284 return Math.sqrt(tx * tx);
285 case 2 :
286 ty = this.y - other.y;
287 return Math.sqrt(tx * tx + ty * ty);
288 case 3 :
289 ty = this.y - other.y;
290 tz = this.z - other.z;
291 return Math.sqrt(tx * tx + ty * ty + tz * tz);
292 default :
293 throw new IllegalArgumentException("Illegal dimension of Point" + this.dimension);
294 }
295 }
296
297 public boolean checkConsistency() {
298 return super.checkConsistency() && (this.dimension == 3 || this.z == 0.0)
299 && (this.haveMeasure || this.m == 0.0);
300 }
301 }
0 /*
1 * PointComposedGeom.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - geometry model
4 *
5 * (C) 2004 Paul Ramsey, pramsey@refractions.net
6 *
7 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
8 *
9 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 */
26 package net.postgis.jdbc.geometry;
27
28 import java.sql.SQLException;
29
30 /**
31 * PointComposedGeom - base class for all composed geoms that contain only
32 * points.
33 *
34 * @author markus.schaber@logix-tt.com
35 *
36 */
37
38 public abstract class PointComposedGeom extends ComposedGeom {
39 /* JDK 1.5 Serialization */
40 private static final long serialVersionUID = 0x100;
41
42 protected PointComposedGeom(int type) {
43 super(type);
44 }
45
46 protected PointComposedGeom(int type, Point[] points) {
47 super(type, points);
48 }
49
50 public PointComposedGeom(int type, String value) throws SQLException {
51 this(type, value, false);
52 }
53
54 public PointComposedGeom(int type, String value, boolean haveM) throws SQLException {
55 super(type, value, haveM);
56 }
57
58 protected Geometry createSubGeomInstance(String token, boolean haveM) throws SQLException {
59 return new Point(token, haveM);
60 }
61
62 protected Geometry[] createSubGeomArray(int pointcount) {
63 return new Point[pointcount];
64 }
65
66 protected void innerWKT(StringBuffer sb) {
67 subgeoms[0].innerWKT(sb);
68 for (int i = 1; i < subgeoms.length; i++) {
69 sb.append(',');
70 subgeoms[i].innerWKT(sb);
71 }
72 }
73
74 /**
75 * optimized version
76 */
77 public int numPoints() {
78 return subgeoms.length;
79 }
80
81 /**
82 * optimized version
83 */
84 public Point getPoint(int idx) {
85 if (idx >= 0 & idx < subgeoms.length) {
86 return (Point) subgeoms[idx];
87 } else {
88 return null;
89 }
90 }
91
92 /**
93 * Get the underlying Point array
94 *
95 * @return an array of Points within this geometry
96 */
97 public Point[] getPoints() {
98 return (Point[]) subgeoms;
99 }
100 }
0 /*
1 * Polygon.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - geometry model
4 *
5 * (C) 2004 Paul Ramsey, pramsey@refractions.net
6 *
7 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
8 *
9 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 */
26
27 package net.postgis.jdbc.geometry;
28
29 import java.sql.SQLException;
30
31 public class Polygon extends ComposedGeom {
32 /* JDK 1.5 Serialization */
33 private static final long serialVersionUID = 0x100;
34
35 public Polygon() {
36 super(POLYGON);
37 }
38
39 public Polygon(LinearRing[] rings) {
40 super(POLYGON, rings);
41 }
42
43 public Polygon(String value) throws SQLException {
44 this(value, false);
45 }
46
47 public Polygon(String value, boolean haveM) throws SQLException {
48 super(POLYGON, value, haveM);
49 }
50
51 protected Geometry createSubGeomInstance(String token, boolean haveM) throws SQLException {
52 return new LinearRing(token, haveM);
53 }
54
55 protected Geometry[] createSubGeomArray(int ringcount) {
56 return new LinearRing[ringcount];
57 }
58
59 public int numRings() {
60 return subgeoms.length;
61 }
62
63 public LinearRing getRing(int idx) {
64 if (idx >= 0 & idx < subgeoms.length) {
65 return (LinearRing) subgeoms[idx];
66 } else {
67 return null;
68 }
69 }
70 }
0 /*
1 * BinaryParser.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - Binary Parser
4 *
5 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
6 *
7 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24 package net.postgis.jdbc.geometry.binary;
25
26 import net.postgis.jdbc.geometry.Geometry;
27 import net.postgis.jdbc.geometry.GeometryCollection;
28 import net.postgis.jdbc.geometry.LineString;
29 import net.postgis.jdbc.geometry.LinearRing;
30 import net.postgis.jdbc.geometry.MultiLineString;
31 import net.postgis.jdbc.geometry.MultiPoint;
32 import net.postgis.jdbc.geometry.MultiPolygon;
33 import net.postgis.jdbc.geometry.Point;
34 import net.postgis.jdbc.geometry.Polygon;
35 import net.postgis.jdbc.geometry.binary.ByteGetter.BinaryByteGetter;
36 import net.postgis.jdbc.geometry.binary.ByteGetter.StringByteGetter;
37
38
39 /**
40 * Parse binary representation of geometries.
41 *
42 * It should be easy to add char[] and CharSequence ByteGetter instances,
43 * although the latter one is not compatible with older jdks.
44 *
45 * I did not implement real unsigned 32-bit integers or emulate them with long,
46 * as both java Arrays and Strings currently can have only 2^31-1 elements
47 * (bytes), so we cannot even get or build Geometries with more than approx.
48 * 2^28 coordinates (8 bytes each).
49 *
50 * @author {@literal Markus Schaber <markus.schaber@logix-tt.com>}
51 *
52 */
53 public class BinaryParser {
54
55 /**
56 * Get the appropriate ValueGetter for my endianness
57 *
58 * @param bytes The appropriate Byte Getter
59 *
60 * @return the ValueGetter
61 */
62 public static ValueGetter valueGetterForEndian(ByteGetter bytes) {
63 if (bytes.get(0) == ValueGetter.XDR.NUMBER) { // XDR
64 return new ValueGetter.XDR(bytes);
65 } else if (bytes.get(0) == ValueGetter.NDR.NUMBER) {
66 return new ValueGetter.NDR(bytes);
67 } else {
68 throw new IllegalArgumentException("Unknown Endian type:" + bytes.get(0));
69 }
70 }
71
72 /**
73 * Parse a hex encoded geometry
74 *
75 * Is synchronized to protect offset counter. (Unfortunately, Java does not
76 * have neither call by reference nor multiple return values.)
77 *
78 * @param value String containing the data to be parsed
79 * @return resulting geometry for the parsed data
80 */
81 public synchronized Geometry parse(String value) {
82 StringByteGetter bytes = new StringByteGetter(value);
83 return parseGeometry(valueGetterForEndian(bytes));
84 }
85
86 /**
87 * Parse a binary encoded geometry.
88 *
89 * Is synchronized to protect offset counter. (Unfortunately, Java does not
90 * have neither call by reference nor multiple return values.)
91 *
92 * @param value byte array containing the data to be parsed
93 * @return resulting geometry for the parsed data
94 */
95 public synchronized Geometry parse(byte[] value) {
96 BinaryByteGetter bytes = new BinaryByteGetter(value);
97 return parseGeometry(valueGetterForEndian(bytes));
98 }
99
100 /**
101 * Parse a geometry starting at offset.
102 *
103 * @param data ValueGetter with the data to be parsed
104 * @return the parsed geometry
105 * */
106 protected Geometry parseGeometry(ValueGetter data) {
107 byte endian = data.getByte(); // skip and test endian flag
108 if (endian != data.endian) {
109 throw new IllegalArgumentException("Endian inconsistency!");
110 }
111 int typeword = data.getInt();
112
113 int realtype = typeword & 0x1FFFFFFF; // cut off high flag bits
114
115 boolean haveZ = (typeword & 0x80000000) != 0;
116 boolean haveM = (typeword & 0x40000000) != 0;
117 boolean haveS = (typeword & 0x20000000) != 0;
118
119 int srid = Geometry.UNKNOWN_SRID;
120
121 if (haveS) {
122 srid = Geometry.parseSRID(data.getInt());
123 }
124 Geometry result1;
125 switch (realtype) {
126 case Geometry.POINT :
127 result1 = parsePoint(data, haveZ, haveM);
128 break;
129 case Geometry.LINESTRING :
130 result1 = parseLineString(data, haveZ, haveM);
131 break;
132 case Geometry.POLYGON :
133 result1 = parsePolygon(data, haveZ, haveM);
134 break;
135 case Geometry.MULTIPOINT :
136 result1 = parseMultiPoint(data);
137 break;
138 case Geometry.MULTILINESTRING :
139 result1 = parseMultiLineString(data);
140 break;
141 case Geometry.MULTIPOLYGON :
142 result1 = parseMultiPolygon(data);
143 break;
144 case Geometry.GEOMETRYCOLLECTION :
145 result1 = parseCollection(data);
146 break;
147 default :
148 throw new IllegalArgumentException("Unknown Geometry Type: " + realtype);
149 }
150
151 Geometry result = result1;
152
153 if (srid != Geometry.UNKNOWN_SRID) {
154 result.setSrid(srid);
155 }
156 return result;
157 }
158
159 private Point parsePoint(ValueGetter data, boolean haveZ, boolean haveM) {
160 double X = data.getDouble();
161 double Y = data.getDouble();
162 Point result;
163 if (haveZ) {
164 double Z = data.getDouble();
165 result = new Point(X, Y, Z);
166 } else {
167 result = new Point(X, Y);
168 }
169
170 if (haveM) {
171 result.setM(data.getDouble());
172 }
173
174 return result;
175 }
176
177 /** Parse an Array of "full" Geometries */
178 private void parseGeometryArray(ValueGetter data, Geometry[] container) {
179 for (int i = 0; i < container.length; i++) {
180 container[i] = parseGeometry(data);
181 }
182 }
183
184 /**
185 * Parse an Array of "slim" Points (without endianness and type, part of
186 * LinearRing and Linestring, but not MultiPoint!
187 *
188 * @param haveZ
189 * @param haveM
190 */
191 private Point[] parsePointArray(ValueGetter data, boolean haveZ, boolean haveM) {
192 int count = data.getInt();
193 Point[] result = new Point[count];
194 for (int i = 0; i < count; i++) {
195 result[i] = parsePoint(data, haveZ, haveM);
196 }
197 return result;
198 }
199
200 private MultiPoint parseMultiPoint(ValueGetter data) {
201 Point[] points = new Point[data.getInt()];
202 parseGeometryArray(data, points);
203 return new MultiPoint(points);
204 }
205
206 private LineString parseLineString(ValueGetter data, boolean haveZ, boolean haveM) {
207 Point[] points = parsePointArray(data, haveZ, haveM);
208 return new LineString(points);
209 }
210
211 private LinearRing parseLinearRing(ValueGetter data, boolean haveZ, boolean haveM) {
212 Point[] points = parsePointArray(data, haveZ, haveM);
213 return new LinearRing(points);
214 }
215
216 private Polygon parsePolygon(ValueGetter data, boolean haveZ, boolean haveM) {
217 int count = data.getInt();
218 LinearRing[] rings = new LinearRing[count];
219 for (int i = 0; i < count; i++) {
220 rings[i] = parseLinearRing(data, haveZ, haveM);
221 }
222 return new Polygon(rings);
223 }
224
225 private MultiLineString parseMultiLineString(ValueGetter data) {
226 int count = data.getInt();
227 LineString[] strings = new LineString[count];
228 parseGeometryArray(data, strings);
229 return new MultiLineString(strings);
230 }
231
232 private MultiPolygon parseMultiPolygon(ValueGetter data) {
233 int count = data.getInt();
234 Polygon[] polys = new Polygon[count];
235 parseGeometryArray(data, polys);
236 return new MultiPolygon(polys);
237 }
238
239 private GeometryCollection parseCollection(ValueGetter data) {
240 int count = data.getInt();
241 Geometry[] geoms = new Geometry[count];
242 parseGeometryArray(data, geoms);
243 return new GeometryCollection(geoms);
244 }
245 }
0 /*
1 * BinaryWriter.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - Binary Writer
4 *
5 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
6 *
7 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24 package net.postgis.jdbc.geometry.binary;
25
26 import net.postgis.jdbc.geometry.Geometry;
27 import net.postgis.jdbc.geometry.GeometryCollection;
28 import net.postgis.jdbc.geometry.LineString;
29 import net.postgis.jdbc.geometry.LinearRing;
30 import net.postgis.jdbc.geometry.MultiLineString;
31 import net.postgis.jdbc.geometry.MultiPoint;
32 import net.postgis.jdbc.geometry.MultiPolygon;
33 import net.postgis.jdbc.geometry.Point;
34 import net.postgis.jdbc.geometry.Polygon;
35
36
37 /**
38 * Create binary representation of geometries. Currently, only text rep (hexed)
39 * implementation is tested.
40 *
41 * It should be easy to add char[] and CharSequence ByteGetter instances,
42 * although the latter one is not compatible with older jdks.
43 *
44 * I did not implement real unsigned 32-bit integers or emulate them with long,
45 * as both java Arrays and Strings currently can have only 2^31-1 elements
46 * (bytes), so we cannot even get or build Geometries with more than approx.
47 * 2^28 coordinates (8 bytes each).
48 *
49 * @author markus.schaber@logi-track.com
50 *
51 */
52 public class BinaryWriter {
53
54 /**
55 * Get the appropriate ValueGetter for my endianness
56 *
57 * @param bytes The ByteSetter to use
58 * @param endian the endian for the ValueSetter to use
59 * @return the ValueGetter
60 */
61 public static ValueSetter valueSetterForEndian(ByteSetter bytes, byte endian) {
62 if (endian == ValueSetter.XDR.NUMBER) { // XDR
63 return new ValueSetter.XDR(bytes);
64 } else if (endian == ValueSetter.NDR.NUMBER) {
65 return new ValueSetter.NDR(bytes);
66 } else {
67 throw new IllegalArgumentException("Unknown Endian type:" + endian);
68 }
69 }
70
71 /**
72 * Write a hex encoded geometry
73 *
74 * Is synchronized to protect offset counter. (Unfortunately, Java does not
75 * have neither call by reference nor multiple return values.) This is a
76 * TODO item.
77 *
78 * The geometry you put in must be consistent, geom.checkConsistency() must
79 * return true. If not, the result may be invalid WKB.
80 *
81 * @see Geometry#checkConsistency() the consistency checker
82 *
83 * @param geom the geometry to be written
84 * @param REP endianness to write the bytes with
85 * @return String containing the hex encoded geometry
86 */
87 public synchronized String writeHexed(Geometry geom, byte REP) {
88 int length = estimateBytes(geom);
89 ByteSetter.StringByteSetter bytes = new ByteSetter.StringByteSetter(length);
90 writeGeometry(geom, valueSetterForEndian(bytes, REP));
91 return bytes.result();
92 }
93
94 public synchronized String writeHexed(Geometry geom) {
95 return writeHexed(geom, ValueSetter.NDR.NUMBER);
96 }
97
98 /**
99 * Write a binary encoded geometry.
100 *
101 * Is synchronized to protect offset counter. (Unfortunately, Java does not
102 * have neither call by reference nor multiple return values.) This is a
103 * TODO item.
104 *
105 * The geometry you put in must be consistent, geom.checkConsistency() must
106 * return true. If not, the result may be invalid WKB.
107 *
108 * @see Geometry#checkConsistency()
109 *
110 * @param geom the geometry to be written
111 * @param REP endianness to write the bytes with
112 * @return byte array containing the encoded geometry
113 */
114 public synchronized byte[] writeBinary(Geometry geom, byte REP) {
115 int length = estimateBytes(geom);
116 ByteSetter.BinaryByteSetter bytes = new ByteSetter.BinaryByteSetter(length);
117 writeGeometry(geom, valueSetterForEndian(bytes, REP));
118 return bytes.result();
119 }
120
121 public synchronized byte[] writeBinary(Geometry geom) {
122 return writeBinary(geom, ValueSetter.NDR.NUMBER);
123 }
124
125 /**
126 * Parse a geometry starting at offset.
127 * @param geom the geometry to write
128 * @param dest the value setting to be used for writing
129 */
130 protected void writeGeometry(Geometry geom, ValueSetter dest) {
131 // write endian flag
132 dest.setByte(dest.endian);
133
134 // write typeword
135 int typeword = geom.type;
136 if (geom.dimension == 3) {
137 typeword |= 0x80000000;
138 }
139 if (geom.haveMeasure) {
140 typeword |= 0x40000000;
141 }
142 if (geom.srid != Geometry.UNKNOWN_SRID) {
143 typeword |= 0x20000000;
144 }
145
146 dest.setInt(typeword);
147
148 if (geom.srid != Geometry.UNKNOWN_SRID) {
149 dest.setInt(geom.srid);
150 }
151
152 switch (geom.type) {
153 case Geometry.POINT :
154 writePoint((Point) geom, dest);
155 break;
156 case Geometry.LINESTRING :
157 writeLineString((LineString) geom, dest);
158 break;
159 case Geometry.POLYGON :
160 writePolygon((Polygon) geom, dest);
161 break;
162 case Geometry.MULTIPOINT :
163 writeMultiPoint((MultiPoint) geom, dest);
164 break;
165 case Geometry.MULTILINESTRING :
166 writeMultiLineString((MultiLineString) geom, dest);
167 break;
168 case Geometry.MULTIPOLYGON :
169 writeMultiPolygon((MultiPolygon) geom, dest);
170 break;
171 case Geometry.GEOMETRYCOLLECTION :
172 writeCollection((GeometryCollection) geom, dest);
173 break;
174 default :
175 throw new IllegalArgumentException("Unknown Geometry Type: " + geom.type);
176 }
177 }
178
179 /**
180 * Writes a "slim" Point (without endiannes, srid ant type, only the
181 * ordinates and measure. Used by writeGeometry as ell as writePointArray.
182 */
183 private void writePoint(Point geom, ValueSetter dest) {
184 dest.setDouble(geom.x);
185 dest.setDouble(geom.y);
186
187 if (geom.dimension == 3) {
188 dest.setDouble(geom.z);
189 }
190
191 if (geom.haveMeasure) {
192 dest.setDouble(geom.m);
193 }
194 }
195
196 /** Write an Array of "full" Geometries */
197 private void writeGeometryArray(Geometry[] container, ValueSetter dest) {
198 for (int i = 0; i < container.length; i++) {
199 writeGeometry(container[i], dest);
200 }
201 }
202
203 /**
204 * Write an Array of "slim" Points (without endianness, srid and type, part
205 * of LinearRing and Linestring, but not MultiPoint!
206 */
207 private void writePointArray(Point[] geom, ValueSetter dest) {
208 // number of points
209 dest.setInt(geom.length);
210 for (int i = 0; i < geom.length; i++) {
211 writePoint(geom[i], dest);
212 }
213 }
214
215 private void writeMultiPoint(MultiPoint geom, ValueSetter dest) {
216 dest.setInt(geom.numPoints());
217 writeGeometryArray(geom.getPoints(), dest);
218 }
219
220 private void writeLineString(LineString geom, ValueSetter dest) {
221 writePointArray(geom.getPoints(), dest);
222 }
223
224 private void writeLinearRing(LinearRing geom, ValueSetter dest) {
225 writePointArray(geom.getPoints(), dest);
226 }
227
228 private void writePolygon(Polygon geom, ValueSetter dest) {
229 dest.setInt(geom.numRings());
230 for (int i = 0; i < geom.numRings(); i++) {
231 writeLinearRing(geom.getRing(i), dest);
232 }
233 }
234
235 private void writeMultiLineString(MultiLineString geom, ValueSetter dest) {
236 dest.setInt(geom.numLines());
237 writeGeometryArray(geom.getLines(), dest);
238 }
239
240 private void writeMultiPolygon(MultiPolygon geom, ValueSetter dest) {
241 dest.setInt(geom.numPolygons());
242 writeGeometryArray(geom.getPolygons(), dest);
243 }
244
245 private void writeCollection(GeometryCollection geom, ValueSetter dest) {
246 dest.setInt(geom.numGeoms());
247 writeGeometryArray(geom.getGeometries(), dest);
248 }
249
250 /**
251 * Estimate how much bytes a geometry will need in WKB.
252 *
253 * @param geom Geometry to estimate.
254 * @return estimated number of bytes
255 */
256 protected int estimateBytes(Geometry geom) {
257 int result = 0;
258
259 // write endian flag
260 result += 1;
261
262 // write typeword
263 result += 4;
264
265 if (geom.srid != Geometry.UNKNOWN_SRID) {
266 result += 4;
267 }
268
269 switch (geom.type) {
270 case Geometry.POINT :
271 result += estimatePoint((Point) geom);
272 break;
273 case Geometry.LINESTRING :
274 result += estimateLineString((LineString) geom);
275 break;
276 case Geometry.POLYGON :
277 result += estimatePolygon((Polygon) geom);
278 break;
279 case Geometry.MULTIPOINT :
280 result += estimateMultiPoint((MultiPoint) geom);
281 break;
282 case Geometry.MULTILINESTRING :
283 result += estimateMultiLineString((MultiLineString) geom);
284 break;
285 case Geometry.MULTIPOLYGON :
286 result += estimateMultiPolygon((MultiPolygon) geom);
287 break;
288 case Geometry.GEOMETRYCOLLECTION :
289 result += estimateCollection((GeometryCollection) geom);
290 break;
291 default :
292 throw new IllegalArgumentException("Unknown Geometry Type: " + geom.type);
293 }
294 return result;
295 }
296
297 private int estimatePoint(Point geom) {
298 // x, y both have 8 bytes
299 int result = 16;
300 if (geom.dimension == 3) {
301 result += 8;
302 }
303
304 if (geom.haveMeasure) {
305 result += 8;
306 }
307 return result;
308 }
309
310 /** Write an Array of "full" Geometries */
311 private int estimateGeometryArray(Geometry[] container) {
312 int result = 0;
313 for (int i = 0; i < container.length; i++) {
314 result += estimateBytes(container[i]);
315 }
316 return result;
317 }
318
319 /**
320 * Write an Array of "slim" Points (without endianness and type, part of
321 * LinearRing and Linestring, but not MultiPoint!
322 */
323 private int estimatePointArray(Point[] geom) {
324 // number of points
325 int result = 4;
326
327 // And the amount of the points itsself, in consistent geometries
328 // all points have equal size.
329 if (geom.length > 0) {
330 result += geom.length * estimatePoint(geom[0]);
331 }
332 return result;
333 }
334
335 private int estimateMultiPoint(MultiPoint geom) {
336 // int size
337 int result = 4;
338 if (geom.numPoints() > 0) {
339 // We can shortcut here, as all subgeoms have the same fixed size
340 result += geom.numPoints() * estimateBytes(geom.getFirstPoint());
341 }
342 return result;
343 }
344
345 private int estimateLineString(LineString geom) {
346 return estimatePointArray(geom.getPoints());
347 }
348
349 private int estimateLinearRing(LinearRing geom) {
350 return estimatePointArray(geom.getPoints());
351 }
352
353 private int estimatePolygon(Polygon geom) {
354 // int length
355 int result = 4;
356 for (int i = 0; i < geom.numRings(); i++) {
357 result += estimateLinearRing(geom.getRing(i));
358 }
359 return result;
360 }
361
362 private int estimateMultiLineString(MultiLineString geom) {
363 // 4-byte count + subgeometries
364 return 4 + estimateGeometryArray(geom.getLines());
365 }
366
367 private int estimateMultiPolygon(MultiPolygon geom) {
368 // 4-byte count + subgeometries
369 return 4 + estimateGeometryArray(geom.getPolygons());
370 }
371
372 private int estimateCollection(GeometryCollection geom) {
373 // 4-byte count + subgeometries
374 return 4 + estimateGeometryArray(geom.getGeometries());
375 }
376 }
0 /*
1 * ByteGetter.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - Binary Parser
4 *
5 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
6 *
7 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24
25 package net.postgis.jdbc.geometry.binary;
26
27 public abstract class ByteGetter {
28 /**
29 * Get a byte.
30 *
31 * @param index the index to get the value from
32 * @return The result is returned as Int to eliminate sign problems when
33 * or'ing several values together.
34 */
35 public abstract int get(int index);
36
37 public static class BinaryByteGetter extends ByteGetter {
38 private byte[] array;
39
40 public BinaryByteGetter(byte[] array) {
41 this.array = array;
42 }
43
44 public int get(int index) {
45 return array[index] & 0xFF; // mask out sign-extended bits.
46 }
47 }
48
49 public static class StringByteGetter extends ByteGetter {
50 private String rep;
51
52 public StringByteGetter(String rep) {
53 this.rep = rep;
54 }
55
56 public int get(int index) {
57 index *= 2;
58 int high = unhex(rep.charAt(index));
59 int low = unhex(rep.charAt(index + 1));
60 return (high << 4) + low;
61 }
62
63 public static byte unhex(char c) {
64 if (c >= '0' && c <= '9') {
65 return (byte) (c - '0');
66 } else if (c >= 'A' && c <= 'F') {
67 return (byte) (c - 'A' + 10);
68 } else if (c >= 'a' && c <= 'f') {
69 return (byte) (c - 'a' + 10);
70 } else {
71 throw new IllegalArgumentException("No valid Hex char " + c);
72 }
73 }
74 }
75 }
0 /*
1 * ByteSetter.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - Binary Parser
4 *
5 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
6 *
7 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24
25 package net.postgis.jdbc.geometry.binary;
26
27 public abstract class ByteSetter {
28
29 /**
30 * Set a byte.
31 *
32 * @param b byte value to set with
33 * @param index index to set
34 */
35 public abstract void set(byte b, int index);
36
37 public static class BinaryByteSetter extends ByteSetter {
38 private byte[] array;
39
40 public BinaryByteSetter(int length) {
41 this.array = new byte[length];
42 }
43
44 public void set(byte b, int index) {
45 array[index] = b; // mask out sign-extended bits.
46 }
47
48 public byte[] result() {
49 return array;
50 }
51
52 public String toString() {
53 char[] arr = new char[array.length];
54 for (int i=0; i<array.length; i++) {
55 arr[i] = (char)(array[i]&0xFF);
56 }
57 return new String(arr);
58 }
59 }
60
61 public static class StringByteSetter extends ByteSetter {
62 protected static final char[] hextypes = "0123456789ABCDEF".toCharArray();
63 private char[] rep;
64
65 public StringByteSetter(int length) {
66 this.rep = new char[length * 2];
67 }
68
69 public void set(byte b, int index) {
70 index *= 2;
71 rep[index] = hextypes[(b >>> 4) & 0xF];
72 rep[index + 1] = hextypes[b & 0xF];
73 }
74
75 public char[] resultAsArray() {
76 return rep;
77 }
78
79 public String result() {
80 return new String(rep);
81 }
82
83 public String toString() {
84 return new String(rep);
85 }
86 }
87 }
0 /*
1 * ValueGetter.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - Binary Parser
4 *
5 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
6 *
7 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24
25 package net.postgis.jdbc.geometry.binary;
26
27 public abstract class ValueGetter {
28 ByteGetter data;
29 int position;
30 public final byte endian;
31
32 public ValueGetter(ByteGetter data, byte endian) {
33 this.data = data;
34 this.endian = endian;
35 }
36
37 /**
38 * Get a byte, should be equal for all endians
39 *
40 * @return the byte value
41 */
42 public byte getByte() {
43 return (byte) data.get(position++);
44 }
45
46 public int getInt() {
47 int res = getInt(position);
48 position += 4;
49 return res;
50 }
51
52 public long getLong() {
53 long res = getLong(position);
54 position += 8;
55 return res;
56 }
57
58 /**
59 * Get a 32-Bit integer
60 *
61 * @param index the index to get the value from
62 * @return the int value
63 */
64 protected abstract int getInt(int index);
65
66 /**
67 * Get a long value. This is not needed directly, but as a nice side-effect
68 * from GetDouble.
69 *
70 * @param index the index to get the value from
71 * @return the long value
72 */
73 protected abstract long getLong(int index);
74
75 /**
76 * Get a double.
77 *
78 * @return the double value
79 */
80 public double getDouble() {
81 long bitrep = getLong();
82 return Double.longBitsToDouble(bitrep);
83 }
84
85 public static class XDR extends ValueGetter {
86 public static final byte NUMBER = 0;
87
88 public XDR(ByteGetter data) {
89 super(data, NUMBER);
90 }
91
92 protected int getInt(int index) {
93 return (data.get(index) << 24) + (data.get(index + 1) << 16)
94 + (data.get(index + 2) << 8) + data.get(index + 3);
95 }
96
97 protected long getLong(int index) {
98 return ((long) data.get(index) << 56) + ((long) data.get(index + 1) << 48)
99 + ((long) data.get(index + 2) << 40) + ((long) data.get(index + 3) << 32)
100 + ((long) data.get(index + 4) << 24) + ((long) data.get(index + 5) << 16)
101 + ((long) data.get(index + 6) << 8) + ((long) data.get(index + 7) << 0);
102 }
103 }
104
105 public static class NDR extends ValueGetter {
106 public static final byte NUMBER = 1;
107
108 public NDR(ByteGetter data) {
109 super(data, NUMBER);
110 }
111
112 protected int getInt(int index) {
113 return (data.get(index + 3) << 24) + (data.get(index + 2) << 16)
114 + (data.get(index + 1) << 8) + data.get(index);
115 }
116
117 protected long getLong(int index) {
118 return ((long) data.get(index + 7) << 56) + ((long) data.get(index + 6) << 48)
119 + ((long) data.get(index + 5) << 40) + ((long) data.get(index + 4) << 32)
120 + ((long) data.get(index + 3) << 24) + ((long) data.get(index + 2) << 16)
121 + ((long) data.get(index + 1) << 8) + ((long) data.get(index) << 0);
122 }
123 }
124 }
0 /*
1 * ValueSetter.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - Binary Parser
4 *
5 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
6 *
7 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24
25 package net.postgis.jdbc.geometry.binary;
26
27 public abstract class ValueSetter {
28 ByteSetter data;
29 int position=0;
30 public final byte endian;
31
32 public ValueSetter(ByteSetter data, byte endian) {
33 this.data = data;
34 this.endian = endian;
35 }
36
37 /**
38 * Set a byte, should be equal for all endians
39 *
40 * @param value byte value to be set with.
41 */
42 public void setByte(byte value) {
43 data.set(value, position);
44 position += 1;
45 }
46
47 public void setInt(int value) {
48 setInt(value, position);
49 position += 4;
50 }
51
52 public void setLong(long value) {
53 setLong(value, position);
54 position += 8;
55 }
56
57 /**
58 * Set a 32-Bit integer
59 *
60 * @param value int value to be set with
61 * @param index int value for the index
62 *
63 */
64 protected abstract void setInt(int value, int index);
65
66 /**
67 * Set a long value. This is not needed directly, but as a nice side-effect
68 * from GetDouble.
69 *
70 * @param data int value to be set with
71 * @param index int value for the index
72 */
73 protected abstract void setLong(long data, int index);
74
75 /**
76 * Set a double.
77 *
78 * @param data double value to be set with
79 */
80 public void setDouble(double data) {
81 long bitrep = Double.doubleToLongBits(data);
82 setLong(bitrep);
83 }
84
85 public String toString() {
86 String name = getClass().getName();
87 int pointpos = name.lastIndexOf('.');
88 String klsName = name.substring(pointpos+1);
89 return klsName+"('"+(data==null?"NULL":data.toString()+"')");
90 }
91
92 public static class XDR extends ValueSetter {
93 public static final byte NUMBER = 0;
94
95 public XDR(ByteSetter data) {
96 super(data, NUMBER);
97 }
98
99 protected void setInt(int value, int index) {
100 data.set((byte) (value >>> 24), index);
101 data.set((byte) (value >>> 16), index + 1);
102 data.set((byte) (value >>> 8), index + 2);
103 data.set((byte) value, index + 3);
104 }
105
106 protected void setLong(long value, int index) {
107 data.set((byte) (value >>> 56), index);
108 data.set((byte) (value >>> 48), index + 1);
109 data.set((byte) (value >>> 40), index + 2);
110 data.set((byte) (value >>> 32), index + 3);
111 data.set((byte) (value >>> 24), index + 4);
112 data.set((byte) (value >>> 16), index + 5);
113 data.set((byte) (value >>> 8), index + 6);
114 data.set((byte) value, index + 7);
115 }
116 }
117
118 public static class NDR extends ValueSetter {
119 public static final byte NUMBER = 1;
120
121 public NDR(ByteSetter data) {
122 super(data, NUMBER);
123 }
124
125 protected void setInt(int value, int index) {
126 data.set((byte) (value >>> 24), index + 3);
127 data.set((byte) (value >>> 16), index + 2);
128 data.set((byte) (value >>> 8), index + 1);
129 data.set((byte) value, index);
130 }
131
132 protected void setLong(long value, int index) {
133 data.set((byte) (value >>> 56), index + 7);
134 data.set((byte) (value >>> 48), index + 6);
135 data.set((byte) (value >>> 40), index + 5);
136 data.set((byte) (value >>> 32), index + 4);
137 data.set((byte) (value >>> 24), index + 3);
138 data.set((byte) (value >>> 16), index + 2);
139 data.set((byte) (value >>> 8), index + 1);
140 data.set((byte) value, index);
141 }
142 }
143 }
0 /*
1 * This library is free software; you can redistribute it and/or
2 * modify it under the terms of the GNU Lesser General Public
3 * License as published by the Free Software Foundation; either
4 * version 2.1 of the License, or (at your option) any later version.
5 *
6 * This library is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 * Lesser General Public License for more details.
10 *
11 * You should have received a copy of the GNU Lesser General Public
12 * License along with this library; if not, write to the Free Software
13 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
14 *
15 * (C) 2020 Phillip Ross, phillip.w.g.ross@gmail.com
16 */
17
18 package net.postgis.jdbc.geometry.util;
19
20
21 /**
22 * An enumeration of existing version functions.
23 *
24 * @author Phillip Ross
25 */
26 public enum VersionFunctions {
27
28 /** The function to return the full version and build configuration info of the PostGIS Server. */
29 POSTGIS_FULL_VERSION,
30
31 /** The function to return the version of the GDAL library. */
32 POSTGIS_GDAL_VERSION,
33
34 /** The function to return the version of the GEOS library. */
35 POSTGIS_GEOS_VERSION,
36
37 /** The function to return the build date of the PostGIS library. */
38 POSTGIS_LIB_BUILD_DATE,
39
40 /** The function to return the version of the PostGIS library. */
41 POSTGIS_LIB_VERSION,
42
43 /** The function to return the version of the libjson library. */
44 POSTGIS_LIBJSON_VERSION,
45
46 /** The function to return the version of the libxml library. */
47 POSTGIS_LIBXML_VERSION,
48
49 /** The function to return the version of the Proj library. */
50 POSTGIS_PROJ_VERSION,
51
52 /** The function to return the version of the raster library. */
53 POSTGIS_RASTER_LIB_VERSION,
54
55 /** The function to return the build date of the scripts. */
56 POSTGIS_SCRIPTS_BUILD_DATE,
57
58 /** The function to return the version of the scripts installed in the database. */
59 POSTGIS_SCRIPTS_INSTALLED,
60
61 /** The function to return the version of the scripts released with the installed PostGIS library. */
62 POSTGIS_SCRIPTS_RELEASED,
63
64 /** The function to return the Subversion version of the PostGIS Server. */
65 POSTGIS_SVN_VERSION,
66
67 /** The function to return the version of the PostGIS Server. */
68 POSTGIS_VERSION
69
70 }
0 /*
1 * This library is free software; you can redistribute it and/or
2 * modify it under the terms of the GNU Lesser General Public
3 * License as published by the Free Software Foundation; either
4 * version 2.1 of the License, or (at your option) any later version.
5 *
6 * This library is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 * Lesser General Public License for more details.
10 *
11 * You should have received a copy of the GNU Lesser General Public
12 * License along with this library; if not, write to the Free Software
13 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
14 *
15 * (C) 2020 Phillip Ross, phillip.w.g.ross@gmail.com
16 */
17
18 package net.postgis.jdbc.geometry.util;
19
20
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
23
24 import java.sql.Connection;
25 import java.sql.PreparedStatement;
26 import java.sql.ResultSet;
27 import java.sql.SQLException;
28 import java.util.Objects;
29
30
31 /**
32 * Utility for working with PostGIS Server version.
33 *
34 * @author Phillip Ross
35 */
36 public class VersionUtil {
37
38 /** The static logger instance. */
39 private static final Logger logger = LoggerFactory.getLogger(VersionUtil.class);
40
41 /** The string to match when determining a function does not exist from the content of an error message. */
42 public static final String NONEXISTENT_FUNCTION_ERROR_MESSAGE_CONTENT = "does not exist";
43
44 /** The token which separates version components within the PostGIS Server version. */
45 public static final String POSTGIS_SERVER_VERSION_SEPERATOR = ".";
46
47 /** The number of seconds to wait for a connection validation operation. */
48 private static final int DEFAULT_CONNECTION_TIMEOUT = 60;
49
50
51 /**
52 * Query a specific version string from the datasource for a specified function.
53 *
54 * @param connection The connection to issue the version query function against.
55 * @param function The version function to use for querying the version.
56 * @return a string version for the specified function.
57 * @throws SQLException when a jdbc exception occurs.
58 */
59 public static String getVersionString(final Connection connection, final String function) throws SQLException {
60 Objects.requireNonNull(connection, "Unable to retrieve version string from a null connection");
61 Objects.requireNonNull(function, "Unable to retrieve version string for a null function");
62 validateConnection(connection);
63
64 String result = "-- unavailable -- ";
65 try (
66 PreparedStatement statement = connection.prepareStatement("SELECT " + function + "()");
67 ResultSet resultSet = statement.executeQuery();
68 ) {
69 if (resultSet.next()) {
70 String version = resultSet.getString(1);
71 if (version != null) {
72 result = version.trim();
73 } else {
74 result = "-- null result --";
75 }
76 } else {
77 result = "-- no result --";
78 }
79 } catch (SQLException sqle) {
80 // If the function does not exist, a SQLException will be thrown, but it should be caught and swallowed if
81 // the non-existent function error message content is found in the error message. The SQLException might
82 // be thrown for some other problem not related to the missing function, so rethrow it if it doesn't
83 // contain the non-existent function error message content.
84 if (!sqle.getMessage().contains(NONEXISTENT_FUNCTION_ERROR_MESSAGE_CONTENT)) {
85 throw sqle;
86 }
87 }
88 return result;
89 }
90
91
92 public static String retrievePostGISServerVersionString(final Connection connection) throws SQLException {
93 Objects.requireNonNull(
94 connection, "Unable to retrieve PostGIS server version string from a null connection"
95 );
96 validateConnection(connection);
97 String postGISVersionString = getVersionString(connection, VersionFunctions.POSTGIS_VERSION.toString());
98 logger.debug("retrieved PostGIS server version string: [{}]", postGISVersionString);
99 return postGISVersionString;
100 }
101
102
103 public static String retrievePostGISServerVersion(final Connection connection) throws SQLException {
104 Objects.requireNonNull(connection, "Unable to retrieve PostGIS version from a null connection");
105 validateConnection(connection);
106 String versionString = retrievePostGISServerVersionString(connection);
107
108 final String versionTerminatorString = " ";
109 final String version;
110 final int versionTerminatorIndex = versionString.indexOf(versionTerminatorString);
111 if (versionTerminatorIndex == -1) {
112 version = versionString;
113 } else {
114 version = versionString.substring(0, versionTerminatorIndex);
115 }
116 logger.debug("retrieved PostGIS server version: [{}]", version);
117 return version;
118 }
119
120
121 public static String retrievePostGISServerMajorVersion(final Connection connection) throws SQLException {
122 Objects.requireNonNull(connection, "Unable to retrieve PostGIS major version from a null connection");
123 validateConnection(connection);
124 String version = retrievePostGISServerVersion(connection);
125 final String majorVersion;
126 final int majorVersionSeperatorIndex = version.indexOf(POSTGIS_SERVER_VERSION_SEPERATOR);
127 if (majorVersionSeperatorIndex == -1) {
128 majorVersion = version;
129 } else {
130 majorVersion = version.substring(0, majorVersionSeperatorIndex);
131 }
132 logger.debug("retrieved postGIS major version string: [{}]", majorVersion);
133 return majorVersion;
134 }
135
136
137 public static String retrievePostGISServerMinorVersion(final Connection connection) throws SQLException {
138 Objects.requireNonNull(connection, "Unable to retrieve PostGIS minor version from a null connection");
139 validateConnection(connection);
140 String version = retrievePostGISServerVersion(connection);
141 final String minorVersion;
142 final int majorVersionSeperatorIndex = version.indexOf(POSTGIS_SERVER_VERSION_SEPERATOR);
143 if (majorVersionSeperatorIndex == -1) {
144 minorVersion = "";
145 } else {
146 final int minorVersionSeperatorIndex =
147 version.indexOf(POSTGIS_SERVER_VERSION_SEPERATOR, majorVersionSeperatorIndex + 1);
148 if (minorVersionSeperatorIndex == -1) {
149 minorVersion = version.substring(majorVersionSeperatorIndex + 1);
150 } else {
151 minorVersion = version.substring(majorVersionSeperatorIndex + 1, minorVersionSeperatorIndex);
152 }
153 }
154 logger.debug("retrieved postGIS minor version string: [{}]", minorVersion);
155 return minorVersion;
156 }
157
158
159 /**
160 * Validates a connection.
161 *
162 * @param connection the connection to be validated.
163 * @throws SQLException when connection is invalid
164 */
165 private static void validateConnection(final Connection connection) throws SQLException {
166 if (!connection.isValid(DEFAULT_CONNECTION_TIMEOUT)) {
167 throw new SQLException("The connection was not valid.");
168 }
169 }
170
171
172 }
0 /**
1 * Utility classes.
2 *
3 * @author Phillip Ross
4 */
5 package net.postgis.jdbc.geometry.util;
0 /*
1 * DatatypesTest.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - example and test classes
4 *
5 * (C) 2004 Paul Ramsey, pramsey@refractions.net
6 *
7 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
8 *
9 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 */
26
27 package net.postgis.jdbc.geometry;
28
29
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32 import org.testng.annotations.Test;
33
34 import java.sql.SQLException;
35
36
37 public class DatatypesTest {
38
39 private static final Logger logger = LoggerFactory.getLogger(DatatypesTest.class);
40
41 private static final String mlng_str = "MULTILINESTRING ((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))";
42
43 private static final String mplg_str = "MULTIPOLYGON (((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))";
44
45 private static final String plg_str = "POLYGON ((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))";
46
47 private static final String lng_str = "LINESTRING (10 10 20,20 20 20, 50 50 50, 34 34 34)";
48
49 private static final String ptg_str = "POINT(10 10 20)";
50
51 private static final String lr_str = "(10 10 20,34 34 34, 23 19 23 , 10 10 11)";
52
53
54 @Test
55 public void testLinearRing() throws SQLException {
56 logger.trace("void testLinearRing()");
57 logger.info(lr_str);
58 LinearRing lr = new LinearRing(lr_str);
59 logger.info(lr.toString());
60 }
61
62
63 @Test
64 public void testPoint() throws SQLException {
65 logger.trace("void testPoint()");
66 logger.info(ptg_str);
67 Point ptg = new Point(ptg_str);
68 logger.info(ptg.toString());
69 }
70
71
72 @Test
73 public void testLineString() throws SQLException {
74 logger.trace("void testLineString()");
75 logger.info(lng_str);
76 LineString lng = new LineString(lng_str);
77 logger.info(lng.toString());
78 }
79
80
81 @Test
82 public void testPolygon() throws SQLException {
83 logger.trace("void testPolygon()");
84 logger.info(plg_str);
85 Polygon plg = new Polygon(plg_str);
86 logger.info(plg.toString());
87 }
88
89
90 @Test
91 public void testMultiPolygon() throws SQLException {
92 logger.trace("void testMultiPolygon()");
93 logger.info(mplg_str);
94 MultiPolygon mplg = new MultiPolygon(mplg_str);
95 logger.info(mplg.toString());
96 }
97
98
99 @Test
100 public void testMultiLineString() throws SQLException {
101 logger.trace("void testMultiLineString()");
102 logger.info(mlng_str);
103 MultiLineString mlng = new MultiLineString(mlng_str);
104 logger.info(mlng.toString());
105 }
106
107
108 }
0 /*
1 * TokenizerTest.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - example and test classes
4 *
5 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 *
21 */
22
23 package net.postgis.jdbc.geometry;
24
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27 import org.testng.annotations.Test;
28
29 import java.util.List;
30
31
32 public class TokenizerTest {
33
34 private static final Logger logger = LoggerFactory.getLogger(TokenizerTest.class);
35
36
37 @Test
38 public void testTokenizer() {
39 char delimiterL1 = ',';
40 char delimiterL2 = ' ';
41 String stringToTokenize = "((1 2 3),(4 5 6),(7 8 9)";
42 logger.debug("tokenizing string value => {}", stringToTokenize);
43 List<String> tokensLevel1 = GeometryTokenizer.tokenize(GeometryTokenizer.removeLeadingAndTrailingStrings(stringToTokenize, "(", ")"), delimiterL1);
44 logger.debug("level 1 tokens [delimiter = {}] [tokenCount = {}]", delimiterL1, tokensLevel1.size());
45 for (String tokenL1 : tokensLevel1) {
46 logger.debug("L1 token => {} / {}", tokenL1, GeometryTokenizer.removeLeadingAndTrailingStrings(tokenL1, "(", ")"));
47 List<String> tokensLevel2 = GeometryTokenizer.tokenize(GeometryTokenizer.removeLeadingAndTrailingStrings(tokenL1, "(", ")"), delimiterL2);
48 logger.debug("level 2 tokens [delimiter = {}] [tokenCount = {}]", delimiterL2, tokensLevel2.size());
49 for (String tokenL2 : tokensLevel2) {
50 logger.debug("L2 token => {} / {}", tokenL2, GeometryTokenizer.removeLeadingAndTrailingStrings(tokenL2, "(", ")"));
51 }
52 }
53 }
54
55 }
0 <configuration debug="false">
1
2 <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
3 <layout class="ch.qos.logback.classic.PatternLayout">
4 <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
5 </layout>
6 </appender>
7
8 <root level="debug">
9 <appender-ref ref="STDOUT" />
10 </root>
11
12 <logger name="com.github.dockerjava" level="ERROR"/>
13 <logger name="org.testcontainers" level="ERROR"/>
14 <logger name="net.postgis" level="ERROR"/>
15
16 </configuration>
0 <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
1 <suite name="Postgis Geometry Test Suite" verbose="1">
2
3 <test name="Postgis Geometry Tests">
4 <classes>
5 <class name="net.postgis.jdbc.geometry.DatatypesTest"/>
6 <class name="net.postgis.jdbc.geometry.TokenizerTest"/>
7 </classes>
8 </test>
9
10 </suite>
44 <parent>
55 <groupId>net.postgis</groupId>
66 <artifactId>postgis-java-aggregator</artifactId>
7 <version>2.5.0</version>
7 <version>2021.1.0</version>
88 </parent>
99
1010 <artifactId>postgis-jdbc-java2d</artifactId>
11 <version>2.5.0</version>
11 <version>2021.1.0</version>
1212 <packaging>jar</packaging>
1313
1414 <name>postgis-jdbc-java2d</name>
1818 <dependency>
1919 <groupId>net.postgis</groupId>
2020 <artifactId>postgis-jdbc</artifactId>
21 <version>2.5.0</version>
21 <version>2021.1.0</version>
2222 </dependency>
2323 <dependency>
2424 <groupId>net.postgis.tools</groupId>
2525 <artifactId>test-utils</artifactId>
26 <version>2.5.0</version>
26 <version>2021.1.0</version>
2727 <scope>test</scope>
2828 </dependency>
2929 </dependencies>
3131 <build>
3232 <plugins>
3333 <plugin>
34 <groupId>org.apache.maven.plugins</groupId>
35 <artifactId>maven-surefire-plugin</artifactId>
34 <artifactId>maven-jar-plugin</artifactId>
3635 <configuration>
37 <suiteXmlFiles>
38 <suiteXmlFile>${project.build.testOutputDirectory}/testng.xml</suiteXmlFile>
39 </suiteXmlFiles>
36 <archive>
37 <manifestEntries>
38 <Automatic-Module-Name>net.postgis.jdbc.java2d</Automatic-Module-Name>
39 </manifestEntries>
40 </archive>
4041 </configuration>
4142 </plugin>
4243 </plugins>
+0
-210
postgis-jdbc-java2d/src/main/java/examples/TestJava2d.java less more
0 /*
1 * TestJava2d.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - example and test classes
4 *
5 * (C) 2004 Paul Ramsey, pramsey@refractions.net
6 *
7 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
8 *
9 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 */
26
27 package examples;
28
29 import java.awt.*;
30 import java.awt.event.WindowEvent;
31 import java.awt.event.WindowListener;
32 import java.awt.geom.AffineTransform;
33 import java.awt.geom.Rectangle2D;
34 import java.sql.Connection;
35 import java.sql.DriverManager;
36 import java.sql.ResultSet;
37 import java.sql.SQLException;
38 import java.util.ArrayList;
39
40 import org.postgis.java2d.Java2DWrapper;
41
42 public class TestJava2d {
43 private static final boolean DEBUG = true;
44
45 public static final Shape[] SHAPEARRAY = new Shape[0];
46
47 public static final String[][] testDataset = new String[][] {
48 {"point1", "POINT(10 11)"},
49 {"multipoint1", "MULTIPOINT(10.25 11,10.5 11,10.75 11,11 11,11.25 11,11.5 11,11.75 11,12 11)"},
50 {"linestring1", "LINESTRING(0 0,100 0,100 100,0 100)"},
51 {"linestring2", "LINESTRING(-310 110,210 110,210 210,-310 210,-310 110)"},
52 {"multilinestring", "MULTILINESTRING((0 0,10 10,20 0,30 10),(40 0,40 10,50 10,50 20,60 20))"},
53 };
54
55 static {
56 new Java2DWrapper(); // make shure our driver is initialized
57 }
58
59 public static void main(String[] args) throws ClassNotFoundException, SQLException {
60
61 if (args.length != 5) {
62 System.err.println("Usage: java examples/TestJava2D dburl user pass tablename column");
63 System.err.println();
64 System.err.println("dburl has the following format:");
65 System.err.println(Java2DWrapper.POSTGIS_PROTOCOL + "//HOST:PORT/DATABASENAME");
66 System.err.println("tablename is 'jdbc_test' by default.");
67 System.exit(1);
68 }
69
70 Shape[] geometries = read(args[0], args[1], args[2], "SELECT " + args[4] + " FROM " + args[3]);
71 if (DEBUG) {
72 System.err.println("read " + geometries.length + " geometries.");
73 }
74 if (geometries.length == 0) {
75 if (DEBUG) {
76 System.err.println("No geometries were read.");
77 }
78 return;
79 }
80
81 System.err.println("Painting...");
82 Frame window = new Frame("PostGIS java2D demo");
83
84 Canvas CV = new GisCanvas(geometries);
85
86 window.add(CV);
87
88 window.setSize(500, 500);
89
90 window.addWindowListener(new EventHandler());
91
92 window.setVisible(true);
93 }
94
95 static Rectangle2D calcbbox(Shape[] geometries) {
96 Rectangle2D bbox = geometries[0].getBounds2D();
97 for (int i = 1; i < geometries.length; i++) {
98 bbox = bbox.createUnion(geometries[i].getBounds2D());
99 }
100 return bbox;
101 }
102
103 private static Shape[] read(String dburl, String dbuser, String dbpass, String query)
104 throws ClassNotFoundException, SQLException {
105 ArrayList geometries = new ArrayList();
106 if (DEBUG) {
107 System.err.println("Creating JDBC connection...");
108 }
109 Class.forName("org.postgresql.Driver");
110 Connection conn = DriverManager.getConnection(dburl, dbuser, dbpass);
111
112 if (DEBUG) {
113 System.err.println("fetching geometries: " + query);
114 }
115 ResultSet r = conn.createStatement().executeQuery(query);
116
117 while (r.next()) {
118 final Shape current = (Shape) r.getObject(1);
119 if (current != null) {
120 geometries.add(current);
121 }
122 }
123 conn.close();
124 return (Shape[]) geometries.toArray(SHAPEARRAY);
125 }
126
127 public static class GisCanvas extends Canvas {
128 /** Keep java 1.5 compiler happy */
129 private static final long serialVersionUID = 1L;
130
131 final Rectangle2D bbox;
132 final Shape[] geometries;
133
134 public GisCanvas(Shape[] geometries) {
135 this.geometries = geometries;
136 this.bbox = calcbbox(geometries);
137 setBackground(Color.GREEN);
138 }
139
140 public void paint(Graphics og) {
141 Graphics2D g = (Graphics2D) og;
142 // Add 5% padding on all borders
143 final double paddingTop = bbox.getHeight() * 0.05;
144 final double paddingBottom = bbox.getHeight() * 0.05;
145 final double paddingLeft = bbox.getWidth() * 0.05;
146 final double paddingRight = bbox.getWidth() * 0.05;
147 // If the bounding box has negative coordinates, we need to offset by the negative coordinate
148 final double offsetX = (bbox.getX() < 0) ? (0 - bbox.getX()) : 0;
149 final double offsetY = (bbox.getY() < 0) ? (0 - bbox.getY()) : 0;
150 // Scale by the bounding box and padding
151 final double scaleX = (super.getWidth() - (paddingLeft + paddingRight)) / (bbox.getWidth());
152 final double scaleY = (super.getHeight() - (paddingTop + paddingBottom)) / (bbox.getHeight());
153 // Apply the transform parameters
154 AffineTransform at = new AffineTransform();
155 at.translate(paddingLeft, paddingTop);
156 at.scale(scaleX, scaleY);
157 at.translate(offsetX, offsetY);
158
159 if (DEBUG) {
160 System.err.println();
161 System.err.println("paddingTop: " + paddingTop);
162 System.err.println("paddingBottom: " + paddingBottom);
163 System.err.println("paddingLeft: " + paddingLeft);
164 System.err.println("paddingRight: " + paddingRight);
165 System.err.println("offsetX: " + offsetX);
166 System.err.println("offsetY: " + offsetY);
167 System.err.println("scaleX: " + scaleX);
168 System.err.println("scaleY: " + scaleY);
169 System.err.println("bbox: " + bbox);
170 System.err.println("trans: " + at);
171 System.err.println("new: " + at.createTransformedShape(bbox).getBounds2D());
172 System.err.println("visual:" + super.getBounds());
173 }
174 for (int i = 0; i < geometries.length; i++) {
175 g.setPaint(Color.BLUE);
176 final Shape shape = at.createTransformedShape(geometries[i]);
177 g.fill(shape);
178 g.setPaint(Color.ORANGE);
179 g.draw(shape);
180 }
181 }
182 }
183
184 public static class EventHandler implements WindowListener {
185
186 public void windowActivated(WindowEvent e) {//
187 }
188
189 public void windowClosed(WindowEvent e) {//
190 }
191
192 public void windowClosing(WindowEvent e) {
193 e.getWindow().setVisible(false);
194 System.exit(0);
195 }
196
197 public void windowDeactivated(WindowEvent e) {//
198 }
199
200 public void windowDeiconified(WindowEvent e) {//
201 }
202
203 public void windowIconified(WindowEvent e) {//
204 }
205
206 public void windowOpened(WindowEvent e) {//
207 }
208 }
209 }
0 module net.postgis.jdbc.java2d {
1 requires java.desktop;
2 requires java.sql;
3
4 requires org.postgresql.jdbc;
5
6 requires net.postgis.geometry;
7 requires net.postgis.jdbc;
8
9 exports net.postgis.jdbc.java2d;
10 }
0 /*
1 * Java2DWrapper.java
2 *
3 * Allows transparent usage of JTS Geometry classes via PostgreSQL JDBC driver
4 * connected to a PostGIS enabled PostgreSQL server.
5 *
6 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
7 *
8 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 *
24 */
25
26 package net.postgis.jdbc.java2d;
27
28 import org.postgresql.Driver;
29 import org.postgresql.PGConnection;
30
31 import java.sql.Connection;
32 import java.sql.SQLException;
33 import java.util.Properties;
34 import java.util.logging.Logger;
35
36 /**
37 * Java2DWrapper
38 *
39 * Wraps the PostGreSQL Driver to add transparent readonly support for PostGIS
40 * objects into java2d path objects.
41 *
42 * This method currently works with J2EE DataSource implementations, and with
43 * DriverManager framework.
44 *
45 * Simply replace the "jdbc:postgresql:" with a "jdbc:postgis_j2d" in the
46 * jdbc URL.
47 *
48 * @author markus.schaber@logix-tt.com
49 *
50 */
51 public class Java2DWrapper extends Driver {
52
53 private static final String POSTGRES_PROTOCOL = "jdbc:postgresql:";
54 public static final String POSTGIS_PROTOCOL = "jdbc:postgis_j2d:";
55 public static final String REVISION = "$Revision$";
56
57 public Java2DWrapper() {
58 super();
59 }
60
61 static {
62 try {
63 // Analogy to org.postgresql.Driver
64 java.sql.DriverManager.registerDriver(new Java2DWrapper());
65 } catch (SQLException e) {
66 e.printStackTrace();
67 }
68 }
69
70 /**
71 * Creates a postgresql connection, and then adds the PostGIS data types to
72 * it calling addpgtypes()
73 *
74 * @param url the URL of the database to connect to
75 * @param info a list of arbitrary tag/value pairs as connection arguments
76 * @return a connection to the URL or null if it isnt us
77 * @exception SQLException if a database access error occurs
78 *
79 * @see java.sql.Driver#connect
80 * @see org.postgresql.Driver
81 */
82 public java.sql.Connection connect(String url, Properties info) throws SQLException {
83 url = mangleURL(url);
84 Connection result = super.connect(url, info);
85 addGISTypes((PGConnection) result);
86 return result;
87 }
88
89
90 /**
91 * Adds the JTS/PostGIS Data types to a PG Connection.
92 *
93 * @throws SQLException when a SQLException occurs
94 * @param pgconn The PGConnection object to add the types to
95 * @throws SQLException when an SQLException occurs
96 */
97 public static void addGISTypes(PGConnection pgconn) throws SQLException {
98 pgconn.addDataType("geometry", PGShapeGeometry.class);
99 pgconn.addDataType("box3d", net.postgis.jdbc.PGbox3d.class);
100 pgconn.addDataType("box2d", net.postgis.jdbc.PGbox2d.class);
101 }
102
103
104 /**
105 * Mangles the PostGIS URL to return the original PostGreSQL URL
106 *
107 * @param url String containing the url to be "mangled"
108 * @return "mangled" string
109 * @throws SQLException when a SQLException occurs
110 */
111 public static String mangleURL(String url) throws SQLException {
112 if (url.startsWith(POSTGIS_PROTOCOL)) {
113 return POSTGRES_PROTOCOL + url.substring(POSTGIS_PROTOCOL.length());
114 } else {
115 throw new SQLException("Unknown protocol or subprotocol in url " + url);
116 }
117 }
118
119 /**
120 * Returns true if the driver thinks it can open a connection to the given
121 * URL. Typically, drivers will return true if they understand the
122 * subprotocol specified in the URL and false if they don't. Our protocols
123 * start with jdbc:postgresql_postGIS:
124 *
125 * @see java.sql.Driver#acceptsURL
126 * @param url the URL of the driver
127 * @return true if this driver accepts the given URL
128 */
129 public boolean acceptsURL(String url) {
130 try {
131 url = mangleURL(url);
132 } catch (SQLException e) {
133 return false;
134 }
135 return super.acceptsURL(url);
136 }
137
138 /**
139 * Gets the underlying drivers major version number
140 *
141 * @return the drivers major version number
142 */
143 public int getMajorVersion() {
144 return super.getMajorVersion();
145 }
146
147 /**
148 * Get the underlying drivers minor version number
149 *
150 * @return the drivers minor version number
151 */
152 public int getMinorVersion() {
153 return super.getMinorVersion();
154 }
155
156
157 /**
158 * Returns our own CVS version plus postgres Version
159 *
160 * @return String identifier for the version
161 */
162 public static String getVersion() {
163 return "Java2DWrapper " + REVISION + ", wrapping " + Driver.getVersion();
164 }
165
166 public Logger getParentLogger() {
167 throw new UnsupportedOperationException("Not supported yet.");
168 }
169 }
0 /*
1 * PGShapeGeometry.java
2 *
3 * Allows PostGIS data to be read directly into a java2d shape
4 *
5 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
6 *
7 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24
25 package net.postgis.jdbc.java2d;
26
27 import java.awt.Rectangle;
28 import java.awt.Shape;
29 import java.awt.geom.*;
30 import java.sql.SQLException;
31
32 import org.postgresql.util.PGobject;
33
34 /**
35 * PostGIS Java2D geometry implementation (read-only).
36 *
37 * Supports PostGIS 1.x (lwgeom hexwkb).
38 *
39 * As the java.awt.Shape methods currently are implemented by using a
40 * java.awt.geom.GeneralPath object, they have the same semantics.
41 *
42 * NOTE: (Multi)Points are translated into a sequence of single MoveTo and LineTo
43 * commands, but WITHOUT a closePath command. When rendering with a stroke that
44 * is not solid, the points may not be rendered.
45 *
46 * (Multi)LineStrings are translated into a sequence of a single MoveTo and
47 * multiple LineTo vertices, and Polygon rings into a sequence of a single
48 * MoveTo, multiple LineTo and a closePath command. To allow correct Polygon
49 * filling, our PathIterators have GeneralPath.WIND_EVEN_ODD as winding rule.
50 *
51 * @see java.awt.geom.GeneralPath
52 * @see java.awt.Shape
53 * @see org.postgresql.util.PGobject
54 *
55 * @author Markus Schaber
56 */
57
58 public class PGShapeGeometry extends PGobject implements Shape {
59 /* JDK 1.5 Serialization */
60 private static final long serialVersionUID = 0x100;
61
62 final static ShapeBinaryParser parser = new ShapeBinaryParser();
63
64 private final GeneralPath path;
65
66 private int srid;
67
68 /**
69 * Constructor called by JDBC drivers. call setValue afterwards to fill with
70 * Geometry data.
71 *
72 */
73 public PGShapeGeometry() {
74 setType("geometry");
75 path = new GeneralPath(GeneralPath.WIND_EVEN_ODD);
76 }
77
78
79 /**
80 * Construct directly from a General Path and SRID value
81 *
82 * @param path GeneralPath to be used
83 * @param srid SRID value to be used
84 */
85 public PGShapeGeometry(GeneralPath path, int srid) {
86 setType("geometry");
87 this.path = path;
88 this.srid = srid;
89 }
90
91
92 /**
93 * Construct with HexWKB representation
94 *
95 * @param value String representation of the HexWKB data
96 * @throws SQLException when a SQLException occurs
97 */
98 public PGShapeGeometry(String value) throws SQLException {
99 this();
100 setValue(value);
101 }
102
103 /**
104 * Reads the HexWKB representation - to be called by the jdbc drivers. Be
105 * shure to call this only once and if you used the PGShapeGeometry()
106 * constructor without parameters. In all other cases, behaviour is
107 * undefined.
108 */
109 public void setValue(String value) throws SQLException {
110 srid = parser.parse(value, path);
111 }
112
113 public String toString() {
114 return "PGShapeGeometry " + path.toString();
115 }
116
117 /** We currently have read-only support, so this method returns null */
118 public String getValue() {
119 return null;
120 }
121
122 public boolean equals(Object obj) {
123 if (obj instanceof PGShapeGeometry)
124 return ((PGShapeGeometry) obj).path.equals(path);
125 return false;
126 }
127
128
129 /**
130 * Return the SRID or Geometry.UNKNOWN_SRID if none was available
131 * @return the SRID value to be used
132 */
133 public int getSRID() {
134 return srid;
135 }
136
137 // following are the java2d Shape method implementations...
138 public boolean contains(double x, double y) {
139 return path.contains(x, y);
140 }
141
142 public boolean contains(double x, double y, double w, double h) {
143 return path.contains(x, y, w, h);
144 }
145
146 public boolean intersects(double x, double y, double w, double h) {
147 return path.intersects(x, y, w, h);
148 }
149
150 public Rectangle getBounds() {
151 return path.getBounds();
152 }
153
154 public boolean contains(Point2D p) {
155 return path.contains(p);
156 }
157
158 public Rectangle2D getBounds2D() {
159 return path.getBounds2D();
160 }
161
162 public boolean contains(Rectangle2D r) {
163 return path.contains(r);
164 }
165
166 public boolean intersects(Rectangle2D r) {
167 return path.intersects(r);
168 }
169
170 public PathIterator getPathIterator(AffineTransform at) {
171 return path.getPathIterator(at);
172 }
173
174 public PathIterator getPathIterator(AffineTransform at, double flatness) {
175 return path.getPathIterator(at, flatness);
176 }
177 }
0 /*
1 * ShapeBinaryParser.java
2 *
3 * Shape Binary Parser for Java2D - relies on net.postgis V1.0.0+ package.
4 *
5 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
6 *
7 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24 package net.postgis.jdbc.java2d;
25
26 import java.awt.geom.GeneralPath;
27
28 import net.postgis.jdbc.geometry.Geometry;
29 import net.postgis.jdbc.geometry.binary.ByteGetter;
30 import net.postgis.jdbc.geometry.binary.ValueGetter;
31 import net.postgis.jdbc.geometry.binary.ByteGetter.BinaryByteGetter;
32 import net.postgis.jdbc.geometry.binary.ByteGetter.StringByteGetter;
33
34 /**
35 * Parse binary representation of geometries. Currently, only text rep (hexed)
36 * implementation is tested.
37 *
38 * It should be easy to add char[] and CharSequence ByteGetter instances,
39 * although the latter one is not compatible with older jdks.
40 *
41 * I did not implement real unsigned 32-bit integers or emulate them with long,
42 * as both java Arrays and Strings currently can have only 2^31-1 elements
43 * (bytes), so we cannot even get or build Geometries with more than approx.
44 * 2^28 coordinates (8 bytes each).
45 *
46 * @author Markus Schaber, markus.schaber@logix-tt.com
47 *
48 */
49 public class ShapeBinaryParser {
50
51 /**
52 * Get the appropriate ValueGetter for my endianness
53 *
54 * @param bytes The appropriate Byte Getter
55 *
56 * @return the ValueGetter
57 */
58 public static ValueGetter valueGetterForEndian(ByteGetter bytes) {
59 if (bytes.get(0) == ValueGetter.XDR.NUMBER) { // XDR
60 return new ValueGetter.XDR(bytes);
61 } else if (bytes.get(0) == ValueGetter.NDR.NUMBER) {
62 return new ValueGetter.NDR(bytes);
63 } else {
64 throw new IllegalArgumentException("Unknown Endian type:" + bytes.get(0));
65 }
66 }
67
68 /**
69 * Parse a hex encoded geometry
70 *
71 * Is synchronized to protect offset counter. (Unfortunately, Java does not
72 * have neither call by reference nor multiple return values.)
73 *
74 * @param value String representation of the value to be parsed
75 * @param path GeneralPath to provide the parsed value to
76 *
77 * @return a potential SRID or Geometry.UNKNOWN_SRID if not present
78 */
79 public synchronized int parse(String value, GeneralPath path) {
80 StringByteGetter bytes = new ByteGetter.StringByteGetter(value);
81 return parseGeometry(valueGetterForEndian(bytes), path);
82 }
83
84 /**
85 * Parse a binary encoded geometry.
86 *
87 * Is synchronized to protect offset counter. (Unfortunately, Java does not
88 * have neither call by reference nor multiple return values.)
89 *
90 * @param value byte array representation of the value to be parsed
91 * @param path GeneralPath to provide the parsed value to
92 *
93 * @return a potential SRID or Geometry.UNKNOWN_SRID if not present
94 */
95 public synchronized int parse(byte[] value, GeneralPath path) {
96 BinaryByteGetter bytes = new ByteGetter.BinaryByteGetter(value);
97 return parseGeometry(valueGetterForEndian(bytes), path);
98 }
99
100 /**
101 * Parse a geometry starting at offset.
102 *
103 * @param data ValueGetter containing the value to be parsed
104 * @param path GeneralPath to provide the parsed value to
105 *
106 * @return a potential SRID or Geometry.UNKNOWN_SRID if not present
107 */
108 protected int parseGeometry(ValueGetter data, GeneralPath path) {
109 byte endian = data.getByte(); // skip and test endian flag
110 if (endian != data.endian) {
111 throw new IllegalArgumentException("Endian inconsistency!");
112 }
113 int typeword = data.getInt();
114
115 int realtype = typeword & 0x1FFFFFFF; // cut off high flag bits
116
117 boolean haveZ = (typeword & 0x80000000) != 0;
118 boolean haveM = (typeword & 0x40000000) != 0;
119 boolean haveS = (typeword & 0x20000000) != 0;
120
121 int srid = Geometry.UNKNOWN_SRID;
122
123 if (haveS) {
124 srid = Geometry.parseSRID(data.getInt());
125 }
126
127 switch (realtype) {
128 case net.postgis.jdbc.geometry.Geometry.POINT :
129 parsePoint(data, haveZ, haveM, path);
130 break;
131 case net.postgis.jdbc.geometry.Geometry.LINESTRING :
132 parseLineString(data, haveZ, haveM, path);
133 break;
134 case net.postgis.jdbc.geometry.Geometry.POLYGON :
135 parsePolygon(data, haveZ, haveM, path);
136 break;
137 case net.postgis.jdbc.geometry.Geometry.MULTIPOINT :
138 parseMultiPoint(data, path);
139 break;
140 case net.postgis.jdbc.geometry.Geometry.MULTILINESTRING :
141 parseMultiLineString(data, path);
142 break;
143 case net.postgis.jdbc.geometry.Geometry.MULTIPOLYGON :
144 parseMultiPolygon(data, path);
145 break;
146 case net.postgis.jdbc.geometry.Geometry.GEOMETRYCOLLECTION :
147 parseCollection(data, path);
148 break;
149 default :
150 throw new IllegalArgumentException("Unknown Geometry Type!");
151 }
152 return srid;
153 }
154
155 private void parsePoint(ValueGetter data, boolean haveZ, boolean haveM, GeneralPath path) {
156 double x = data.getDouble();
157 double y = data.getDouble();
158 path.moveTo(x, y);
159 path.lineTo(x, y);
160 skipZM(data, haveZ, haveM);
161 }
162
163 private void skipZM(ValueGetter data, boolean haveZ, boolean haveM) {
164 if (haveZ) { // skip Z value
165 data.getDouble();
166 }
167 if (haveM) { // skip M value
168 data.getDouble();
169 }
170 }
171
172 /** Parse an Array of "full" Geometries */
173 private void parseGeometryArray(ValueGetter data, int count, GeneralPath path) {
174 for (int i = 0; i < count; i++) {
175 parseGeometry(data, path);
176 }
177 }
178
179 /**
180 * Parse an Array of "slim" Points (without endianness and type, part of
181 * LinearRing and Linestring, but not MultiPoint!
182 *
183 * @param data ValueGetter containing the value to be parsed
184 * @param haveZ flag indicating if Z values exist
185 * @param haveM flag indicating if M values exist
186 * @param path GeneralPath to provide the parsed value to
187 */
188 private void parseCS(ValueGetter data, boolean haveZ, boolean haveM, GeneralPath path) {
189 int count = data.getInt();
190 if (count > 0) {
191 path.moveTo((float) data.getDouble(), (float) data.getDouble());
192 skipZM(data, haveZ, haveM);
193 for (int i = 1; i < count; i++) {
194 path.lineTo((float) data.getDouble(), (float) data.getDouble());
195 skipZM(data, haveZ, haveM);
196 }
197 }
198 }
199
200
201 private void parseMultiPoint(ValueGetter data, GeneralPath path) {
202 parseGeometryArray(data, data.getInt(), path);
203 }
204
205 private void parseLineString(ValueGetter data, boolean haveZ, boolean haveM, GeneralPath path) {
206 parseCS(data, haveZ, haveM, path);
207 }
208
209 private void parseLinearRing(ValueGetter data, boolean haveZ, boolean haveM, GeneralPath path) {
210 parseCS(data, haveZ, haveM, path);
211 path.closePath();
212 }
213
214 private void parsePolygon(ValueGetter data, boolean haveZ, boolean haveM, GeneralPath path) {
215 int holecount = data.getInt() - 1;
216 // parse shell
217 parseLinearRing(data, haveZ, haveM, path);
218 // parse inner rings
219 for (int i = 0; i < holecount; i++) {
220 parseLinearRing(data, haveZ, haveM, path);
221 }
222 }
223
224 private void parseMultiLineString(ValueGetter data, GeneralPath path) {
225 int count = data.getInt();
226 parseGeometryArray(data, count, path);
227 }
228
229 private void parseMultiPolygon(ValueGetter data, GeneralPath path) {
230 int count = data.getInt();
231 parseGeometryArray(data, count, path);
232 }
233
234 private void parseCollection(ValueGetter data, GeneralPath path) {
235 int count = data.getInt();
236 parseGeometryArray(data, count, path);
237 }
238 }
+0
-171
postgis-jdbc-java2d/src/main/java/org/postgis/java2d/Java2DWrapper.java less more
0 /*
1 * Java2DWrapper.java
2 *
3 * Allows transparent usage of JTS Geometry classes via PostgreSQL JDBC driver
4 * connected to a PostGIS enabled PostgreSQL server.
5 *
6 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
7 *
8 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 *
24 */
25
26 package org.postgis.java2d;
27
28 import org.postgresql.Driver;
29 import org.postgresql.PGConnection;
30
31 import java.sql.Connection;
32 import java.sql.SQLException;
33 import java.sql.SQLFeatureNotSupportedException;
34 import java.util.Properties;
35 import java.util.logging.Logger;
36
37 /**
38 * Java2DWrapper
39 *
40 * Wraps the PostGreSQL Driver to add transparent readonly support for PostGIS
41 * objects into java2d path objects.
42 *
43 * This method currently works with J2EE DataSource implementations, and with
44 * DriverManager framework.
45 *
46 * Simply replace the "jdbc:postgresql:" with a "jdbc:postgis_j2d" in the
47 * jdbc URL.
48 *
49 * @author markus.schaber@logix-tt.com
50 *
51 */
52 public class Java2DWrapper extends Driver {
53
54 private static final String POSTGRES_PROTOCOL = "jdbc:postgresql:";
55 public static final String POSTGIS_PROTOCOL = "jdbc:postgis_j2d:";
56 public static final String REVISION = "$Revision$";
57
58 public Java2DWrapper() {
59 super();
60 }
61
62 static {
63 try {
64 // Analogy to org.postgresql.Driver
65 java.sql.DriverManager.registerDriver(new Java2DWrapper());
66 } catch (SQLException e) {
67 e.printStackTrace();
68 }
69 }
70
71 /**
72 * Creates a postgresql connection, and then adds the PostGIS data types to
73 * it calling addpgtypes()
74 *
75 * @param url the URL of the database to connect to
76 * @param info a list of arbitrary tag/value pairs as connection arguments
77 * @return a connection to the URL or null if it isnt us
78 * @exception SQLException if a database access error occurs
79 *
80 * @see java.sql.Driver#connect
81 * @see org.postgresql.Driver
82 */
83 public java.sql.Connection connect(String url, Properties info) throws SQLException {
84 url = mangleURL(url);
85 Connection result = super.connect(url, info);
86 addGISTypes((PGConnection) result);
87 return result;
88 }
89
90
91 /**
92 * Adds the JTS/PostGIS Data types to a PG Connection.
93 *
94 * @throws SQLException when a SQLException occurs
95 * @param pgconn The PGConnection object to add the types to
96 * @throws SQLException when an SQLException occurs
97 */
98 public static void addGISTypes(PGConnection pgconn) throws SQLException {
99 pgconn.addDataType("geometry", PGShapeGeometry.class);
100 pgconn.addDataType("box3d", org.postgis.PGbox3d.class);
101 pgconn.addDataType("box2d", org.postgis.PGbox2d.class);
102 }
103
104
105 /**
106 * Mangles the PostGIS URL to return the original PostGreSQL URL
107 *
108 * @param url String containing the url to be "mangled"
109 * @return "mangled" string
110 * @throws SQLException when a SQLException occurs
111 */
112 public static String mangleURL(String url) throws SQLException {
113 if (url.startsWith(POSTGIS_PROTOCOL)) {
114 return POSTGRES_PROTOCOL + url.substring(POSTGIS_PROTOCOL.length());
115 } else {
116 throw new SQLException("Unknown protocol or subprotocol in url " + url);
117 }
118 }
119
120 /**
121 * Returns true if the driver thinks it can open a connection to the given
122 * URL. Typically, drivers will return true if they understand the
123 * subprotocol specified in the URL and false if they don't. Our protocols
124 * start with jdbc:postgresql_postGIS:
125 *
126 * @see java.sql.Driver#acceptsURL
127 * @param url the URL of the driver
128 * @return true if this driver accepts the given URL
129 */
130 public boolean acceptsURL(String url) {
131 try {
132 url = mangleURL(url);
133 } catch (SQLException e) {
134 return false;
135 }
136 return super.acceptsURL(url);
137 }
138
139 /**
140 * Gets the underlying drivers major version number
141 *
142 * @return the drivers major version number
143 */
144 public int getMajorVersion() {
145 return super.getMajorVersion();
146 }
147
148 /**
149 * Get the underlying drivers minor version number
150 *
151 * @return the drivers minor version number
152 */
153 public int getMinorVersion() {
154 return super.getMinorVersion();
155 }
156
157
158 /**
159 * Returns our own CVS version plus postgres Version
160 *
161 * @return String identifier for the version
162 */
163 public static String getVersion() {
164 return "Java2DWrapper " + REVISION + ", wrapping " + Driver.getVersion();
165 }
166
167 public Logger getParentLogger() {
168 throw new UnsupportedOperationException("Not supported yet.");
169 }
170 }
+0
-178
postgis-jdbc-java2d/src/main/java/org/postgis/java2d/PGShapeGeometry.java less more
0 /*
1 * PGShapeGeometry.java
2 *
3 * Allows PostGIS data to be read directly into a java2d shape
4 *
5 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
6 *
7 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24
25 package org.postgis.java2d;
26
27 import java.awt.Rectangle;
28 import java.awt.Shape;
29 import java.awt.geom.*;
30 import java.sql.SQLException;
31
32 import org.postgresql.util.PGobject;
33
34 /**
35 * PostGIS Java2D geometry implementation (read-only).
36 *
37 * Supports PostGIS 1.x (lwgeom hexwkb).
38 *
39 * As the java.awt.Shape methods currently are implemented by using a
40 * java.awt.geom.GeneralPath object, they have the same semantics.
41 *
42 * NOTE: (Multi)Points are translated into a sequence of single MoveTo and LineTo
43 * commands, but WITHOUT a closePath command. When rendering with a stroke that
44 * is not solid, the points may not be rendered.
45 *
46 * (Multi)LineStrings are translated into a sequence of a single MoveTo and
47 * multiple LineTo vertices, and Polygon rings into a sequence of a single
48 * MoveTo, multiple LineTo and a closePath command. To allow correct Polygon
49 * filling, our PathIterators have GeneralPath.WIND_EVEN_ODD as winding rule.
50 *
51 * @see java.awt.geom.GeneralPath
52 * @see java.awt.Shape
53 * @see org.postgresql.util.PGobject
54 *
55 * @author Markus Schaber
56 */
57
58 public class PGShapeGeometry extends PGobject implements Shape {
59 /* JDK 1.5 Serialization */
60 private static final long serialVersionUID = 0x100;
61
62 final static ShapeBinaryParser parser = new ShapeBinaryParser();
63
64 private final GeneralPath path;
65
66 private int srid;
67
68 /**
69 * Constructor called by JDBC drivers. call setValue afterwards to fill with
70 * Geometry data.
71 *
72 */
73 public PGShapeGeometry() {
74 setType("geometry");
75 path = new GeneralPath(GeneralPath.WIND_EVEN_ODD);
76 }
77
78
79 /**
80 * Construct directly from a General Path and SRID value
81 *
82 * @param path GeneralPath to be used
83 * @param srid SRID value to be used
84 */
85 public PGShapeGeometry(GeneralPath path, int srid) {
86 setType("geometry");
87 this.path = path;
88 this.srid = srid;
89 }
90
91
92 /**
93 * Construct with HexWKB representation
94 *
95 * @param value String representation of the HexWKB data
96 * @throws SQLException when a SQLException occurs
97 */
98 public PGShapeGeometry(String value) throws SQLException {
99 this();
100 setValue(value);
101 }
102
103 /**
104 * Reads the HexWKB representation - to be called by the jdbc drivers. Be
105 * shure to call this only once and if you used the PGShapeGeometry()
106 * constructor without parameters. In all other cases, behaviour is
107 * undefined.
108 */
109 public void setValue(String value) throws SQLException {
110 srid = parser.parse(value, path);
111 }
112
113 public String toString() {
114 return "PGShapeGeometry " + path.toString();
115 }
116
117 /** We currently have read-only support, so this method returns null */
118 public String getValue() {
119 return null;
120 }
121
122 public boolean equals(Object obj) {
123 if (obj instanceof PGShapeGeometry)
124 return ((PGShapeGeometry) obj).path.equals(path);
125 return false;
126 }
127
128
129 /**
130 * Return the SRID or Geometry.UNKNOWN_SRID if none was available
131 * @return the SRID value to be used
132 */
133 public int getSRID() {
134 return srid;
135 }
136
137 // following are the java2d Shape method implementations...
138 public boolean contains(double x, double y) {
139 return path.contains(x, y);
140 }
141
142 public boolean contains(double x, double y, double w, double h) {
143 return path.contains(x, y, w, h);
144 }
145
146 public boolean intersects(double x, double y, double w, double h) {
147 return path.intersects(x, y, w, h);
148 }
149
150 public Rectangle getBounds() {
151 return path.getBounds();
152 }
153
154 public boolean contains(Point2D p) {
155 return path.contains(p);
156 }
157
158 public Rectangle2D getBounds2D() {
159 return path.getBounds2D();
160 }
161
162 public boolean contains(Rectangle2D r) {
163 return path.contains(r);
164 }
165
166 public boolean intersects(Rectangle2D r) {
167 return path.intersects(r);
168 }
169
170 public PathIterator getPathIterator(AffineTransform at) {
171 return path.getPathIterator(at);
172 }
173
174 public PathIterator getPathIterator(AffineTransform at, double flatness) {
175 return path.getPathIterator(at, flatness);
176 }
177 }
+0
-239
postgis-jdbc-java2d/src/main/java/org/postgis/java2d/ShapeBinaryParser.java less more
0 /*
1 * ShapeBinaryParser.java
2 *
3 * Shape Binary Parser for Java2D - relies on org.postgis V1.0.0+ package.
4 *
5 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
6 *
7 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24 package org.postgis.java2d;
25
26 import java.awt.geom.GeneralPath;
27
28 import org.postgis.Geometry;
29 import org.postgis.binary.ByteGetter;
30 import org.postgis.binary.ValueGetter;
31 import org.postgis.binary.ByteGetter.BinaryByteGetter;
32 import org.postgis.binary.ByteGetter.StringByteGetter;
33
34 /**
35 * Parse binary representation of geometries. Currently, only text rep (hexed)
36 * implementation is tested.
37 *
38 * It should be easy to add char[] and CharSequence ByteGetter instances,
39 * although the latter one is not compatible with older jdks.
40 *
41 * I did not implement real unsigned 32-bit integers or emulate them with long,
42 * as both java Arrays and Strings currently can have only 2^31-1 elements
43 * (bytes), so we cannot even get or build Geometries with more than approx.
44 * 2^28 coordinates (8 bytes each).
45 *
46 * @author Markus Schaber, markus.schaber@logix-tt.com
47 *
48 */
49 public class ShapeBinaryParser {
50
51 /**
52 * Get the appropriate ValueGetter for my endianness
53 *
54 * @param bytes The appropriate Byte Getter
55 *
56 * @return the ValueGetter
57 */
58 public static ValueGetter valueGetterForEndian(ByteGetter bytes) {
59 if (bytes.get(0) == ValueGetter.XDR.NUMBER) { // XDR
60 return new ValueGetter.XDR(bytes);
61 } else if (bytes.get(0) == ValueGetter.NDR.NUMBER) {
62 return new ValueGetter.NDR(bytes);
63 } else {
64 throw new IllegalArgumentException("Unknown Endian type:" + bytes.get(0));
65 }
66 }
67
68 /**
69 * Parse a hex encoded geometry
70 *
71 * Is synchronized to protect offset counter. (Unfortunately, Java does not
72 * have neither call by reference nor multiple return values.)
73 *
74 * @param value String representation of the value to be parsed
75 * @param path GeneralPath to provide the parsed value to
76 *
77 * @return a potential SRID or Geometry.UNKNOWN_SRID if not present
78 */
79 public synchronized int parse(String value, GeneralPath path) {
80 StringByteGetter bytes = new ByteGetter.StringByteGetter(value);
81 return parseGeometry(valueGetterForEndian(bytes), path);
82 }
83
84 /**
85 * Parse a binary encoded geometry.
86 *
87 * Is synchronized to protect offset counter. (Unfortunately, Java does not
88 * have neither call by reference nor multiple return values.)
89 *
90 * @param value byte array representation of the value to be parsed
91 * @param path GeneralPath to provide the parsed value to
92 *
93 * @return a potential SRID or Geometry.UNKNOWN_SRID if not present
94 */
95 public synchronized int parse(byte[] value, GeneralPath path) {
96 BinaryByteGetter bytes = new ByteGetter.BinaryByteGetter(value);
97 return parseGeometry(valueGetterForEndian(bytes), path);
98 }
99
100 /**
101 * Parse a geometry starting at offset.
102 *
103 * @param data ValueGetter containing the value to be parsed
104 * @param path GeneralPath to provide the parsed value to
105 *
106 * @return a potential SRID or Geometry.UNKNOWN_SRID if not present
107 */
108 protected int parseGeometry(ValueGetter data, GeneralPath path) {
109 byte endian = data.getByte(); // skip and test endian flag
110 if (endian != data.endian) {
111 throw new IllegalArgumentException("Endian inconsistency!");
112 }
113 int typeword = data.getInt();
114
115 int realtype = typeword & 0x1FFFFFFF; // cut off high flag bits
116
117 boolean haveZ = (typeword & 0x80000000) != 0;
118 boolean haveM = (typeword & 0x40000000) != 0;
119 boolean haveS = (typeword & 0x20000000) != 0;
120
121 int srid = Geometry.UNKNOWN_SRID;
122
123 if (haveS) {
124 srid = Geometry.parseSRID(data.getInt());
125 }
126
127 switch (realtype) {
128 case org.postgis.Geometry.POINT :
129 parsePoint(data, haveZ, haveM, path);
130 break;
131 case org.postgis.Geometry.LINESTRING :
132 parseLineString(data, haveZ, haveM, path);
133 break;
134 case org.postgis.Geometry.POLYGON :
135 parsePolygon(data, haveZ, haveM, path);
136 break;
137 case org.postgis.Geometry.MULTIPOINT :
138 parseMultiPoint(data, path);
139 break;
140 case org.postgis.Geometry.MULTILINESTRING :
141 parseMultiLineString(data, path);
142 break;
143 case org.postgis.Geometry.MULTIPOLYGON :
144 parseMultiPolygon(data, path);
145 break;
146 case org.postgis.Geometry.GEOMETRYCOLLECTION :
147 parseCollection(data, path);
148 break;
149 default :
150 throw new IllegalArgumentException("Unknown Geometry Type!");
151 }
152 return srid;
153 }
154
155 private void parsePoint(ValueGetter data, boolean haveZ, boolean haveM, GeneralPath path) {
156 double x = data.getDouble();
157 double y = data.getDouble();
158 path.moveTo(x, y);
159 path.lineTo(x, y);
160 skipZM(data, haveZ, haveM);
161 }
162
163 private void skipZM(ValueGetter data, boolean haveZ, boolean haveM) {
164 if (haveZ) { // skip Z value
165 data.getDouble();
166 }
167 if (haveM) { // skip M value
168 data.getDouble();
169 }
170 }
171
172 /** Parse an Array of "full" Geometries */
173 private void parseGeometryArray(ValueGetter data, int count, GeneralPath path) {
174 for (int i = 0; i < count; i++) {
175 parseGeometry(data, path);
176 }
177 }
178
179 /**
180 * Parse an Array of "slim" Points (without endianness and type, part of
181 * LinearRing and Linestring, but not MultiPoint!
182 *
183 * @param data ValueGetter containing the value to be parsed
184 * @param haveZ flag indicating if Z values exist
185 * @param haveM flag indicating if M values exist
186 * @param path GeneralPath to provide the parsed value to
187 */
188 private void parseCS(ValueGetter data, boolean haveZ, boolean haveM, GeneralPath path) {
189 int count = data.getInt();
190 if (count > 0) {
191 path.moveTo((float) data.getDouble(), (float) data.getDouble());
192 skipZM(data, haveZ, haveM);
193 for (int i = 1; i < count; i++) {
194 path.lineTo((float) data.getDouble(), (float) data.getDouble());
195 skipZM(data, haveZ, haveM);
196 }
197 }
198 }
199
200
201 private void parseMultiPoint(ValueGetter data, GeneralPath path) {
202 parseGeometryArray(data, data.getInt(), path);
203 }
204
205 private void parseLineString(ValueGetter data, boolean haveZ, boolean haveM, GeneralPath path) {
206 parseCS(data, haveZ, haveM, path);
207 }
208
209 private void parseLinearRing(ValueGetter data, boolean haveZ, boolean haveM, GeneralPath path) {
210 parseCS(data, haveZ, haveM, path);
211 path.closePath();
212 }
213
214 private void parsePolygon(ValueGetter data, boolean haveZ, boolean haveM, GeneralPath path) {
215 int holecount = data.getInt() - 1;
216 // parse shell
217 parseLinearRing(data, haveZ, haveM, path);
218 // parse inner rings
219 for (int i = 0; i < holecount; i++) {
220 parseLinearRing(data, haveZ, haveM, path);
221 }
222 }
223
224 private void parseMultiLineString(ValueGetter data, GeneralPath path) {
225 int count = data.getInt();
226 parseGeometryArray(data, count, path);
227 }
228
229 private void parseMultiPolygon(ValueGetter data, GeneralPath path) {
230 int count = data.getInt();
231 parseGeometryArray(data, count, path);
232 }
233
234 private void parseCollection(ValueGetter data, GeneralPath path) {
235 int count = data.getInt();
236 parseGeometryArray(data, count, path);
237 }
238 }
0 /*
1 * SimpleJava2DWrapperTest.java
2 *
3 * SimpleJava2DWrapperTest for Java2D - relies on net.postgis V1.0.0+ package.
4 *
5 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 *
21 */
22 package net.postgis.jdbc.java2d;
23
24
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27 import org.testng.annotations.Test;
28
29
30 /**
31 * This class serves as little more than an initial placeholder for establishing test classes within
32 * this module's test suite.
33 *
34 * @author Phillip Ross {@literal <phillip.w.g.ross@gmail.com>}
35 */
36 public class SimpleJava2DWrapperTest {
37
38 private static final Logger logger = LoggerFactory.getLogger(SimpleJava2DWrapperTest.class);
39
40 private static final String JAVA2D_WRAPPER_CLASS_NAME = "net.postgis.jdbc.java2d.Java2DWrapper";
41
42
43 @Test
44 public void testWrapperClassLoad() throws Exception {
45 logger.debug("Loading java2d wrapper class: {}", JAVA2D_WRAPPER_CLASS_NAME);
46 Class.forName(JAVA2D_WRAPPER_CLASS_NAME);
47 }
48
49
50 }
+0
-51
postgis-jdbc-java2d/src/test/java/org/postgis/java2d/SimpleJava2DWrapperTest.java less more
0 /*
1 * SimpleJava2DWrapperTest.java
2 *
3 * SimpleJava2DWrapperTest for Java2D - relies on org.postgis V1.0.0+ package.
4 *
5 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 *
21 */
22 package org.postgis.java2d;
23
24
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27 import org.testng.annotations.Test;
28
29
30 /**
31 * This class serves as little more than an initial placeholder for establishing test classes within
32 * this module's test suite.
33 *
34 * @author Phillip Ross {@literal <phillip.w.g.ross@gmail.com>}
35 */
36 public class SimpleJava2DWrapperTest {
37
38 private static final Logger logger = LoggerFactory.getLogger(SimpleJava2DWrapperTest.class);
39
40 private static final String JAVA2D_WRAPPER_CLASS_NAME = "org.postgis.java2d.Java2DWrapper";
41
42
43 @Test
44 public void testWrapperClassLoad() throws Exception {
45 logger.debug("Loading java2d wrapper class: {}", JAVA2D_WRAPPER_CLASS_NAME);
46 Class.forName(JAVA2D_WRAPPER_CLASS_NAME);
47 }
48
49
50 }
99 <appender-ref ref="STDOUT" />
1010 </root>
1111
12 <logger name="org.postgis.java2d" level="ERROR"/>
12 <logger name="net.postgis.jdbc.java2d" level="ERROR"/>
1313
1414 </configuration>
22
33 <test name="PostGIS JDBC Java2D Tests">
44 <classes>
5 <class name="org.postgis.java2d.SimpleJava2DWrapperTest"/>
5 <class name="net.postgis.jdbc.java2d.SimpleJava2DWrapperTest"/>
66 </classes>
77 </test>
88
0 <?xml version="1.0" encoding="UTF-8"?>
1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
2 <modelVersion>4.0.0</modelVersion>
3
4 <parent>
5 <groupId>net.postgis</groupId>
6 <artifactId>postgis-java-aggregator</artifactId>
7 <version>2021.1.0</version>
8 </parent>
9
10 <artifactId>postgis-jdbc-jts</artifactId>
11 <version>2021.1.0</version>
12 <packaging>jar</packaging>
13
14 <name>Postgis JDBC Driver JTS Parser</name>
15 <description>Parser between JTS and PostGIS geometry formats.</description>
16
17 <properties />
18
19 <dependencies>
20 <dependency>
21 <groupId>net.postgis</groupId>
22 <artifactId>postgis-jdbc</artifactId>
23 <version>2021.1.0</version>
24 </dependency>
25 <dependency>
26 <groupId>org.locationtech.jts</groupId>
27 <artifactId>jts-core</artifactId>
28 <version>${dependency.jts-version.version}</version>
29 </dependency>
30 <dependency>
31 <groupId>org.locationtech.spatial4j</groupId>
32 <artifactId>spatial4j</artifactId>
33 <version>${dependency.spatial4j.version}</version>
34 </dependency>
35 <dependency>
36 <groupId>net.postgis.tools</groupId>
37 <artifactId>test-utils</artifactId>
38 <version>2021.1.0</version>
39 <scope>test</scope>
40 </dependency>
41 </dependencies>
42
43 <build>
44 <testResources>
45 <testResource>
46 <directory>src/test/resources</directory>
47 </testResource>
48 <testResource>
49 <directory>src/test/resources-filtered</directory>
50 <filtering>true</filtering>
51 </testResource>
52 </testResources>
53 <plugins>
54 <plugin>
55 <artifactId>maven-jar-plugin</artifactId>
56 <configuration>
57 <archive>
58 <manifestEntries>
59 <Automatic-Module-Name>net.postgis.jdbc.jts</Automatic-Module-Name>
60 </manifestEntries>
61 </archive>
62 </configuration>
63 </plugin>
64 <plugin>
65 <groupId>org.apache.maven.plugins</groupId>
66 <artifactId>maven-failsafe-plugin</artifactId>
67 <executions>
68 <execution>
69 <id>integration-tests</id>
70 <goals>
71 <goal>integration-test</goal>
72 <goal>verify</goal>
73 </goals>
74 <configuration>
75 <skip>${maven.integration.test.skip}</skip>
76 <forkCount>${failsafe.forkCount}</forkCount>
77 <useSystemClassLoader>${failsafe.useSystemClassLoader}</useSystemClassLoader>
78 <suiteXmlFiles>
79 <suiteXmlFile>${project.build.testOutputDirectory}/testng-it.xml</suiteXmlFile>
80 </suiteXmlFiles>
81 </configuration>
82 </execution>
83 </executions>
84 </plugin>
85 <plugin>
86 <groupId>org.apache.maven.plugins</groupId>
87 <artifactId>maven-surefire-plugin</artifactId>
88 <configuration>
89 <skip>true</skip>
90 </configuration>
91 </plugin>
92 </plugins>
93 </build>
94
95 </project>
0 module net.postgis.jdbc.jts {
1 requires java.desktop;
2 requires java.sql;
3
4 requires org.locationtech.jts;
5 requires org.postgresql.jdbc;
6
7 requires spatial4j;
8
9 requires net.postgis.geometry;
10 requires net.postgis.jdbc;
11
12 exports net.postgis.jdbc.jts;
13 }
0 /*
1 * JTSShape.java
2 *
3 * Binary Parser for JTS - relies on net.postgis V1.0.0+ package.
4 *
5 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
6 *
7 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24
25 package net.postgis.jdbc.jts;
26
27 import org.locationtech.jts.geom.*;
28 import org.locationtech.jts.geom.Point;
29 import org.locationtech.jts.geom.Polygon;
30 import org.locationtech.jts.geom.impl.PackedCoordinateSequence;
31
32 import java.awt.*;
33 import java.awt.geom.AffineTransform;
34 import java.awt.geom.PathIterator;
35 import java.awt.geom.Point2D;
36 import java.awt.geom.Rectangle2D;
37
38 public class JTSShape implements Shape {
39 static GeometryFactory fac = new GeometryFactory();
40
41 Geometry geom;
42
43 final static LinearRing[] NOSHELLS = {};
44
45 public JTSShape(Geometry _geom) {
46 this.geom = _geom;
47 }
48
49 public JTSShape(JtsGeometry _geom) {
50 this(_geom.getGeometry());
51 }
52
53 public boolean contains(Point2D p) {
54 return contains(p.getX(), p.getY());
55 }
56
57 public boolean contains(double x, double y) {
58 Coordinate c = new Coordinate(x, y);
59 Point p = fac.createPoint(c);
60 return geom.contains(p);
61 }
62
63 public boolean contains(Rectangle2D r) {
64 return contains(r.getMinX(), r.getMinY(), r.getWidth(), r.getHeight());
65 }
66
67 public boolean contains(double x, double y, double w, double h) {
68 Polygon p = createRect(x, y, w, h);
69 return geom.contains(p);
70 }
71
72 protected Polygon createRect(double x, double y, double w, double h) {
73 Coordinate[] coords = { new Coordinate(x, y), new Coordinate(x + w, y), new Coordinate(x + w, y + h) ,new Coordinate(x, y + h) ,new Coordinate(x, y) };
74 PackedCoordinateSequence shell = new PackedCoordinateSequence.Double(coords, 2);
75 Polygon p = fac.createPolygon(fac.createLinearRing(shell), NOSHELLS);
76 return p;
77 }
78
79 public Rectangle2D getBounds2D() {
80 Envelope env = geom.getEnvelopeInternal();
81 return new Rectangle2D.Double(env.getMinX(), env.getMaxX(), env.getWidth(), env.getHeight());
82 }
83
84 public Rectangle getBounds() {
85 // We deal simple code for efficiency here, the getBounds() rounding
86 // rules are ugly...
87 return getBounds2D().getBounds();
88 }
89
90 public PathIterator getPathIterator(AffineTransform at) {
91 return getPathIterator(geom, at);
92 }
93
94 public PathIterator getPathIterator(AffineTransform at, double flatness) {
95 // we don't have much work here, as we only have linear segments, no
96 // "flattening" necessary.
97 return getPathIterator(at);
98 }
99
100 public boolean intersects(Rectangle2D r) {
101 return intersects(r.getMinX(), r.getMinY(), r.getWidth(), r.getHeight());
102 }
103
104 public boolean intersects(double x, double y, double w, double h) {
105 Polygon p = createRect(x, y, w, h);
106 return geom.intersects(p);
107 }
108
109 public static GeometryPathIterator getPathIterator(Geometry geometry, AffineTransform _at) {
110 if (geometry instanceof Point) {
111 return new PointPathIterator((Point) geometry, _at);
112 } else if (geometry instanceof LineString) {
113 return new LineStringPathIterator((LineString) geometry, _at);
114 } else if (geometry instanceof Polygon) {
115 return new PolygonPathIterator((Polygon) geometry, _at);
116 } else {
117 return new GeometryCollectionPathIterator((GeometryCollection) geometry, _at);
118 }
119 }
120
121 public static abstract class GeometryPathIterator implements PathIterator {
122
123 protected final AffineTransform at;
124 protected int index=0;
125
126 GeometryPathIterator(AffineTransform _at) {
127 this.at = _at;
128 }
129
130 public final int getWindingRule() {
131 return PathIterator.WIND_EVEN_ODD;
132 }
133
134 public void next() {
135 index++;
136 }
137 }
138
139 public static class PointPathIterator extends GeometryPathIterator {
140 final Point p;
141
142 public PointPathIterator(Point _p, AffineTransform _at) {
143 super(_at);
144 p = _p;
145 }
146
147 public int currentSegment(float[] coords) {
148 switch (index) {
149 case 0:
150 coords[0] = (float) p.getX();
151 coords[1] = (float) p.getY();
152 at.transform(coords, 0, coords, 0, 1);
153 return PathIterator.SEG_MOVETO;
154 case 1:
155 return PathIterator.SEG_CLOSE;
156 default:
157 throw new IllegalStateException();
158 }
159 }
160
161 public int currentSegment(double[] coords) {
162 switch (index) {
163 case 0:
164 coords[0] = p.getX();
165 coords[1] = p.getY();
166 at.transform(coords, 0, coords, 0, 1);
167 return PathIterator.SEG_MOVETO;
168 case 1:
169 return PathIterator.SEG_CLOSE;
170 default:
171 throw new IllegalStateException();
172 }
173 }
174
175 public boolean isDone() {
176 return index > 1;
177 }
178 }
179
180 public static class LineStringPathIterator extends GeometryPathIterator {
181 CoordinateSequence cs;
182
183 final boolean isRing;
184
185 public LineStringPathIterator(LineString ls, AffineTransform _at) {
186 super(_at);
187 cs = ls.getCoordinateSequence();
188 isRing = ls instanceof LinearRing;
189 }
190
191 /**
192 * only to be called from PolygonPathIterator subclass
193 * @param _cs A coordinate sequence to be used.
194 */
195 protected void reInit(CoordinateSequence _cs) {
196 cs = _cs;
197 index=0;
198 }
199
200 public int currentSegment(float[] coords) {
201 if (index == 0) {
202 coords[0] = (float) cs.getOrdinate(index, 0);
203 coords[1] = (float) cs.getOrdinate(index, 1);
204 at.transform(coords, 0, coords, 0, 1);
205 return PathIterator.SEG_MOVETO;
206 } else if (index < cs.size()) {
207 coords[0] = (float) cs.getOrdinate(index, 0);
208 coords[1] = (float) cs.getOrdinate(index, 1);
209 at.transform(coords, 0, coords, 0, 1);
210 return PathIterator.SEG_LINETO;
211 } else if (isRing && index == cs.size()) {
212 return PathIterator.SEG_CLOSE;
213 } else {
214 throw new IllegalStateException();
215 }
216 }
217
218 public int currentSegment(double[] coords) {
219 if (index == 0) {
220 coords[0] = cs.getOrdinate(index, 0);
221 coords[1] = cs.getOrdinate(index, 1);
222 at.transform(coords, 0, coords, 0, 1);
223 return PathIterator.SEG_MOVETO;
224 } else if (index < cs.size()) {
225 coords[0] = cs.getOrdinate(index, 0);
226 coords[1] = cs.getOrdinate(index, 1);
227 at.transform(coords, 0, coords, 0, 1);
228 return PathIterator.SEG_LINETO;
229 } else if (isRing && index == cs.size()) {
230 return PathIterator.SEG_CLOSE;
231 } else {
232 throw new IllegalStateException();
233 }
234 }
235
236 public boolean isDone() {
237 return isRing ? index > cs.size() : index >= cs.size();
238 }
239 }
240
241 public static class PolygonPathIterator extends LineStringPathIterator {
242 final Polygon pg;
243 int outerindex=-1;
244
245 public PolygonPathIterator(Polygon _pg, AffineTransform _at) {
246 super(_pg.getExteriorRing() ,_at);
247 pg=_pg;
248 index = -1;
249 }
250
251 public boolean isDone() {
252 return outerindex >= pg.getNumInteriorRing();
253 }
254
255 public void next() {
256 super.next();
257 if (super.isDone()) {
258 outerindex++;
259 if (outerindex < pg.getNumInteriorRing()) {
260 super.reInit(pg.getInteriorRingN(outerindex).getCoordinateSequence());
261 }
262 }
263 }
264 }
265
266 public static class GeometryCollectionPathIterator extends GeometryPathIterator {
267 final GeometryCollection coll;
268 GeometryPathIterator current;
269
270 public GeometryCollectionPathIterator(GeometryCollection _coll, AffineTransform _at) {
271 super(_at);
272 coll = _coll;
273 current = getPathIterator(coll.getGeometryN(index), _at);
274 }
275
276 public boolean isDone() {
277 return index > coll.getNumGeometries();
278 }
279
280 public void next() {
281 current.next();
282 if (current.isDone()) {
283 index++;
284 if (index < coll.getNumGeometries()) {
285 current = getPathIterator(coll.getGeometryN(index), at);
286 }
287 }
288 }
289
290 public int currentSegment(float[] coords) {
291 return current.currentSegment(coords);
292 }
293
294 public int currentSegment(double[] coords) {
295 return current.currentSegment(coords);
296 }
297 }
298 }
0 /*
1 * JtsBinaryParser.java
2 *
3 * Binary Parser for JTS - relies on net.postgis V1.0.0+ package.
4 *
5 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
6 *
7 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24 package net.postgis.jdbc.jts;
25
26 import org.locationtech.jts.geom.*;
27 import org.locationtech.jts.geom.impl.PackedCoordinateSequence;
28 import org.locationtech.spatial4j.context.jts.JtsSpatialContextFactory;
29 import net.postgis.jdbc.geometry.binary.ByteGetter;
30 import net.postgis.jdbc.geometry.binary.ByteGetter.BinaryByteGetter;
31 import net.postgis.jdbc.geometry.binary.ByteGetter.StringByteGetter;
32 import net.postgis.jdbc.geometry.binary.ValueGetter;
33
34 /**
35 * Parse binary representation of geometries. Currently, only text rep (hexed)
36 * implementation is tested.
37 *
38 * It should be easy to add char[] and CharSequence ByteGetter instances,
39 * although the latter one is not compatible with older jdks.
40 *
41 * I did not implement real unsigned 32-bit integers or emulate them with long,
42 * as both java Arrays and Strings currently can have only 2^31-1 elements
43 * (bytes), so we cannot even get or build Geometries with more than approx.
44 * 2^28 coordinates (8 bytes each).
45 *
46 * @author Markus Schaber, markus.schaber@logix-tt.com
47 *
48 */
49 public class JtsBinaryParser {
50
51 private JtsSpatialContextFactory jtsFactory = new JtsSpatialContextFactory();
52
53 /**
54 * Get the appropriate ValueGetter for my endianness
55 *
56 * @param bytes
57 * The appropriate Byte Getter
58 *
59 * @return the ValueGetter
60 */
61 public static ValueGetter valueGetterForEndian(ByteGetter bytes) {
62 if (bytes.get(0) == ValueGetter.XDR.NUMBER) { // XDR
63 return new ValueGetter.XDR(bytes);
64 } else if (bytes.get(0) == ValueGetter.NDR.NUMBER) {
65 return new ValueGetter.NDR(bytes);
66 } else {
67 throw new IllegalArgumentException("Unknown Endian type:" + bytes.get(0));
68 }
69 }
70
71
72 /**
73 * Parse a hex encoded geometry
74 * @param value String containing the hex data to be parsed
75 * @return the resulting parsed geometry
76 */
77 public Geometry parse(String value) {
78 StringByteGetter bytes = new ByteGetter.StringByteGetter(value);
79 return parseGeometry(valueGetterForEndian(bytes));
80 }
81
82
83 /**
84 * Parse a binary encoded geometry.
85 * @param value byte array containing the binary encoded geometru
86 * @return the resulting parsed geometry
87 */
88 public Geometry parse(byte[] value) {
89 BinaryByteGetter bytes = new ByteGetter.BinaryByteGetter(value);
90 return parseGeometry(valueGetterForEndian(bytes));
91 }
92
93
94 /**
95 * Parse a geometry starting at offset.
96 * @param data ValueGetter for the data to be parsed
97 * @return The resulting Geometry
98 */
99 protected Geometry parseGeometry(ValueGetter data) {
100 return parseGeometry(data, 0, false);
101 }
102
103
104 /**
105 * Parse with a known geometry factory
106 * @param data ValueGetter for the data to be parsed
107 * @param srid the SRID to be used for parsing
108 * @param inheritSrid flag to toggle inheriting SRIDs
109 * @return The resulting Geometry
110 */
111 protected Geometry parseGeometry(ValueGetter data, int srid, boolean inheritSrid) {
112 byte endian = data.getByte(); // skip and test endian flag
113 if (endian != data.endian) {
114 throw new IllegalArgumentException("Endian inconsistency!");
115 }
116 int typeword = data.getInt();
117
118 int realtype = typeword & 0x1FFFFFFF; // cut off high flag bits
119
120 boolean haveZ = (typeword & 0x80000000) != 0;
121 boolean haveM = (typeword & 0x40000000) != 0;
122 boolean haveS = (typeword & 0x20000000) != 0;
123
124 if (haveS) {
125 int newsrid = net.postgis.jdbc.geometry.Geometry.parseSRID(data.getInt());
126 if (inheritSrid && newsrid != srid) {
127 throw new IllegalArgumentException("Inconsistent srids in complex geometry: " + srid + ", " + newsrid);
128 } else {
129 srid = newsrid;
130 }
131 } else if (!inheritSrid) {
132 srid = net.postgis.jdbc.geometry.Geometry.UNKNOWN_SRID;
133 }
134
135 Geometry result;
136 switch (realtype) {
137 case net.postgis.jdbc.geometry.Geometry.POINT:
138 result = parsePoint(data, haveZ, haveM);
139 break;
140 case net.postgis.jdbc.geometry.Geometry.LINESTRING:
141 result = parseLineString(data, haveZ, haveM);
142 break;
143 case net.postgis.jdbc.geometry.Geometry.POLYGON:
144 result = parsePolygon(data, haveZ, haveM, srid);
145 break;
146 case net.postgis.jdbc.geometry.Geometry.MULTIPOINT:
147 result = parseMultiPoint(data, srid);
148 break;
149 case net.postgis.jdbc.geometry.Geometry.MULTILINESTRING:
150 result = parseMultiLineString(data, srid);
151 break;
152 case net.postgis.jdbc.geometry.Geometry.MULTIPOLYGON:
153 result = parseMultiPolygon(data, srid);
154 break;
155 case net.postgis.jdbc.geometry.Geometry.GEOMETRYCOLLECTION:
156 result = parseCollection(data, srid);
157 break;
158 default:
159 throw new IllegalArgumentException("Unknown Geometry Type!");
160 }
161
162 result.setSRID(srid);
163
164 return result;
165 }
166
167 private Point parsePoint(ValueGetter data, boolean haveZ, boolean haveM) {
168 double X = data.getDouble();
169 double Y = data.getDouble();
170 Point result;
171 if (haveZ) {
172 double Z = data.getDouble();
173 result = jtsFactory.getGeometryFactory().createPoint(new Coordinate(X, Y, Z));
174 } else {
175 result = jtsFactory.getGeometryFactory().createPoint(new Coordinate(X, Y));
176 }
177
178 if (haveM) { // skip M value
179 data.getDouble();
180 }
181
182 return result;
183 }
184
185 /** Parse an Array of "full" Geometries */
186 private void parseGeometryArray(ValueGetter data, Geometry[] container, int srid) {
187 for (int i = 0; i < container.length; i++) {
188 container[i] = parseGeometry(data, srid, true);
189 }
190 }
191
192 /**
193 * Parse an Array of "slim" Points (without endianness and type, part of
194 * LinearRing and Linestring, but not MultiPoint!
195 *
196 * @param haveZ
197 * @param haveM
198 */
199 private CoordinateSequence parseCS(ValueGetter data, boolean haveZ, boolean haveM) {
200 int count = data.getInt();
201 int dims = haveZ ? 3 : 2;
202 CoordinateSequence cs = new PackedCoordinateSequence.Double(count, dims, 0);
203
204 for (int i = 0; i < count; i++) {
205 for (int d = 0; d < dims; d++) {
206 cs.setOrdinate(i, d, data.getDouble());
207 }
208 if (haveM) { // skip M value
209 data.getDouble();
210 }
211 }
212 return cs;
213 }
214
215 private MultiPoint parseMultiPoint(ValueGetter data, int srid) {
216 Point[] points = new Point[data.getInt()];
217 parseGeometryArray(data, points, srid);
218 return jtsFactory.getGeometryFactory().createMultiPoint(points);
219 }
220
221 private LineString parseLineString(ValueGetter data, boolean haveZ, boolean haveM) {
222 return jtsFactory.getGeometryFactory().createLineString(parseCS(data, haveZ, haveM));
223 }
224
225 private LinearRing parseLinearRing(ValueGetter data, boolean haveZ, boolean haveM) {
226 return jtsFactory.getGeometryFactory().createLinearRing(parseCS(data, haveZ, haveM));
227 }
228
229 private Polygon parsePolygon(ValueGetter data, boolean haveZ, boolean haveM, int srid) {
230 int holecount = data.getInt() - 1;
231 LinearRing[] rings = new LinearRing[holecount];
232 LinearRing shell = parseLinearRing(data, haveZ, haveM);
233 shell.setSRID(srid);
234 for (int i = 0; i < holecount; i++) {
235 rings[i] = parseLinearRing(data, haveZ, haveM);
236 rings[i].setSRID(srid);
237 }
238 return jtsFactory.getGeometryFactory().createPolygon(shell, rings);
239 }
240
241 private MultiLineString parseMultiLineString(ValueGetter data, int srid) {
242 int count = data.getInt();
243 LineString[] strings = new LineString[count];
244 parseGeometryArray(data, strings, srid);
245 return jtsFactory.getGeometryFactory().createMultiLineString(strings);
246 }
247
248 private MultiPolygon parseMultiPolygon(ValueGetter data, int srid) {
249 int count = data.getInt();
250 Polygon[] polys = new Polygon[count];
251 parseGeometryArray(data, polys, srid);
252 return jtsFactory.getGeometryFactory().createMultiPolygon(polys);
253 }
254
255 private GeometryCollection parseCollection(ValueGetter data, int srid) {
256 int count = data.getInt();
257 Geometry[] geoms = new Geometry[count];
258 parseGeometryArray(data, geoms, srid);
259 return jtsFactory.getGeometryFactory().createGeometryCollection(geoms);
260 }
261 }
0 /*
1 * JtsBinaryWriter.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - Binary Writer
4 *
5 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
6 *
7 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24 package net.postgis.jdbc.jts;
25
26 import org.locationtech.jts.geom.CoordinateSequence;
27 import org.locationtech.jts.geom.Geometry;
28 import org.locationtech.jts.geom.GeometryCollection;
29 import org.locationtech.jts.geom.LineString;
30 import org.locationtech.jts.geom.MultiLineString;
31 import org.locationtech.jts.geom.MultiPoint;
32 import org.locationtech.jts.geom.MultiPolygon;
33 import org.locationtech.jts.geom.Point;
34 import org.locationtech.jts.geom.Polygon;
35
36 import net.postgis.jdbc.geometry.binary.ByteSetter;
37 import net.postgis.jdbc.geometry.binary.ValueSetter;
38
39 /**
40 * Create binary representation of geometries. Currently, only text rep (hexed)
41 * implementation is tested. Supports only 2 dimensional geometries.
42 *
43 * It should be easy to add char[] and CharSequence ByteGetter instances,
44 * although the latter one is not compatible with older jdks.
45 *
46 * I did not implement real unsigned 32-bit integers or emulate them with long,
47 * as both java Arrays and Strings currently can have only 2^31-1 elements
48 * (bytes), so we cannot even get or build Geometries with more than approx.
49 * 2^28 coordinates (8 bytes each).
50 *
51 * @author markus.schaber@logi-track.com
52 *
53 */
54 public class JtsBinaryWriter {
55
56 /**
57 * Get the appropriate ValueGetter for my endianness
58 *
59 * @param bytes The ByteSetter
60 * @param endian The endian to be used
61 * @return the appropriate ValueSetter for the specified endian
62 */
63 public static ValueSetter valueSetterForEndian(ByteSetter bytes, byte endian) {
64 if (endian == ValueSetter.XDR.NUMBER) { // XDR
65 return new ValueSetter.XDR(bytes);
66 } else if (endian == ValueSetter.NDR.NUMBER) {
67 return new ValueSetter.NDR(bytes);
68 } else {
69 throw new IllegalArgumentException("Unknown Endian type:" + endian);
70 }
71 }
72
73 /**
74 * Write a hex encoded geometry
75 *
76 * Currently, geometries with more than 2 dimensions and measures are not
77 * cleanly supported, but SRID is honored.
78 *
79 * @param geom The geometry to be written
80 * @param REP The endianness representation to use for writing
81 * @return String containing the hex-encoded geometry
82 */
83 public String writeHexed(Geometry geom, byte REP) {
84 int length = estimateBytes(geom);
85 ByteSetter.StringByteSetter bytes = new ByteSetter.StringByteSetter(length);
86 writeGeometry(geom, valueSetterForEndian(bytes, REP));
87 return bytes.result();
88 }
89
90 public String writeHexed(Geometry geom) {
91 return writeHexed(geom, ValueSetter.NDR.NUMBER);
92 }
93
94 /**
95 * Write a binary encoded geometry.
96 *
97 * Currently, geometries with more than 2 dimensions and measures are not
98 * cleanly supported, but SRID is honored.
99 *
100 * @param geom The geometry to be written
101 * @param REP The endianness representation to use for writing
102 * @return byte array containing the encoded geometry
103 */
104 public byte[] writeBinary(Geometry geom, byte REP) {
105 int length = estimateBytes(geom);
106 ByteSetter.BinaryByteSetter bytes = new ByteSetter.BinaryByteSetter(length);
107 writeGeometry(geom, valueSetterForEndian(bytes, REP));
108 return bytes.result();
109 }
110
111 public byte[] writeBinary(Geometry geom) {
112 return writeBinary(geom, ValueSetter.NDR.NUMBER);
113 }
114
115
116 /**
117 * Parse a geometry starting at offset.
118 * @param geom The Geometry to be written
119 * @param dest The ValueSettr to write to
120 */
121 protected void writeGeometry(Geometry geom, ValueSetter dest) {
122 final int dimension;
123 if (geom == null) {
124 throw new NullPointerException();
125 } else if (geom.isEmpty()) {
126 // don't set any flag bits
127 dimension = 0;
128 } else {
129 dimension = getCoordDim(geom);
130 if (dimension < 2 || dimension > 4) {
131 throw new IllegalArgumentException("Unsupported geometry dimensionality: " + dimension);
132 }
133 }
134 // write endian flag
135 dest.setByte(dest.endian);
136
137 // write typeword
138 final int plaintype = getWKBType(geom);
139 int typeword = plaintype;
140 if (dimension == 3 || dimension == 4) {
141 typeword |= 0x80000000;
142 }
143 if (dimension == 4) {
144 typeword |= 0x40000000;
145 }
146
147 final boolean haveSrid = checkSrid(geom);
148 if (haveSrid) {
149 typeword |= 0x20000000;
150 }
151
152 dest.setInt(typeword);
153
154 if (haveSrid) {
155 dest.setInt(geom.getSRID());
156 }
157
158 switch (plaintype) {
159 case net.postgis.jdbc.geometry.Geometry.POINT:
160 writePoint((Point) geom, dest);
161 break;
162 case net.postgis.jdbc.geometry.Geometry.LINESTRING:
163 writeLineString((LineString) geom, dest);
164 break;
165 case net.postgis.jdbc.geometry.Geometry.POLYGON:
166 writePolygon((Polygon) geom, dest);
167 break;
168 case net.postgis.jdbc.geometry.Geometry.MULTIPOINT:
169 writeMultiPoint((MultiPoint) geom, dest);
170 break;
171 case net.postgis.jdbc.geometry.Geometry.MULTILINESTRING:
172 writeMultiLineString((MultiLineString) geom, dest);
173 break;
174 case net.postgis.jdbc.geometry.Geometry.MULTIPOLYGON:
175 writeMultiPolygon((MultiPolygon) geom, dest);
176 break;
177 case net.postgis.jdbc.geometry.Geometry.GEOMETRYCOLLECTION:
178 writeCollection((GeometryCollection) geom, dest);
179 break;
180 default:
181 throw new IllegalArgumentException("Unknown Geometry Type: " + plaintype);
182 }
183 }
184
185 public static int getWKBType(Geometry geom) {
186 // We always write empty geometries as empty collections - for OpenGIS
187 // conformance
188 if (geom.isEmpty()) {
189 return net.postgis.jdbc.geometry.Geometry.GEOMETRYCOLLECTION;
190 } else if (geom instanceof Point) {
191 return net.postgis.jdbc.geometry.Geometry.POINT;
192 } else if (geom instanceof org.locationtech.jts.geom.LineString) {
193 return net.postgis.jdbc.geometry.Geometry.LINESTRING;
194 } else if (geom instanceof org.locationtech.jts.geom.Polygon) {
195 return net.postgis.jdbc.geometry.Geometry.POLYGON;
196 } else if (geom instanceof MultiPoint) {
197 return net.postgis.jdbc.geometry.Geometry.MULTIPOINT;
198 } else if (geom instanceof MultiLineString) {
199 return net.postgis.jdbc.geometry.Geometry.MULTILINESTRING;
200 } else if (geom instanceof org.locationtech.jts.geom.MultiPolygon) {
201 return net.postgis.jdbc.geometry.Geometry.MULTIPOLYGON;
202 } if (geom instanceof org.locationtech.jts.geom.GeometryCollection) {
203 return net.postgis.jdbc.geometry.Geometry.GEOMETRYCOLLECTION;
204 } else {
205 throw new IllegalArgumentException("Unknown Geometry Type: " + geom.getClass().getName());
206 }
207 }
208
209 /**
210 * Writes a "slim" Point (without endiannes, srid ant type, only the
211 * ordinates and measure. Used by writeGeometry.
212 */
213 private void writePoint(Point geom, ValueSetter dest) {
214 writeCoordinates(geom.getCoordinateSequence(), getCoordDim(geom), dest);
215 }
216
217 /**
218 * Write a CoordinateSequence, part of LinearRing and Linestring, but not
219 * MultiPoint!
220 */
221 private void writeCoordinates(CoordinateSequence seq, int dims, ValueSetter dest) {
222 for (int i = 0; i < seq.size(); i++) {
223 for (int d = 0; d < dims; d++) {
224 dest.setDouble(seq.getOrdinate(i, d));
225 }
226 }
227 }
228
229 private void writeMultiPoint(MultiPoint geom, ValueSetter dest) {
230 dest.setInt(geom.getNumPoints());
231 for (int i = 0; i < geom.getNumPoints(); i++) {
232 writeGeometry(geom.getGeometryN(i), dest);
233 }
234 }
235
236 private void writeLineString(LineString geom, ValueSetter dest) {
237 dest.setInt(geom.getNumPoints());
238 writeCoordinates(geom.getCoordinateSequence(), getCoordDim(geom), dest);
239 }
240
241 private void writePolygon(Polygon geom, ValueSetter dest) {
242 dest.setInt(geom.getNumInteriorRing() + 1);
243 writeLineString(geom.getExteriorRing(), dest);
244 for (int i = 0; i < geom.getNumInteriorRing(); i++) {
245 writeLineString(geom.getInteriorRingN(i), dest);
246 }
247 }
248
249 private void writeMultiLineString(MultiLineString geom, ValueSetter dest) {
250 writeGeometryArray(geom, dest);
251 }
252
253 private void writeMultiPolygon(MultiPolygon geom, ValueSetter dest) {
254 writeGeometryArray(geom, dest);
255 }
256
257 private void writeCollection(GeometryCollection geom, ValueSetter dest) {
258 writeGeometryArray(geom, dest);
259 }
260
261 private void writeGeometryArray(Geometry geom, ValueSetter dest) {
262 dest.setInt(geom.getNumGeometries());
263 for (int i = 0; i < geom.getNumGeometries(); i++) {
264 writeGeometry(geom.getGeometryN(i), dest);
265 }
266 }
267
268
269 /**
270 * Estimate how much bytes a geometry will need in WKB.
271 * @param geom Geometry to estimate
272 * @return number of bytes needed
273 */
274 protected int estimateBytes(Geometry geom) {
275 int result = 0;
276
277 // write endian flag
278 result += 1;
279
280 // write typeword
281 result += 4;
282
283 if (checkSrid(geom)) {
284 result += 4;
285 }
286
287 switch (getWKBType(geom)) {
288 case net.postgis.jdbc.geometry.Geometry.POINT:
289 result += estimatePoint((Point) geom);
290 break;
291 case net.postgis.jdbc.geometry.Geometry.LINESTRING:
292 result += estimateLineString((LineString) geom);
293 break;
294 case net.postgis.jdbc.geometry.Geometry.POLYGON:
295 result += estimatePolygon((Polygon) geom);
296 break;
297 case net.postgis.jdbc.geometry.Geometry.MULTIPOINT:
298 result += estimateMultiPoint((MultiPoint) geom);
299 break;
300 case net.postgis.jdbc.geometry.Geometry.MULTILINESTRING:
301 result += estimateMultiLineString((MultiLineString) geom);
302 break;
303 case net.postgis.jdbc.geometry.Geometry.MULTIPOLYGON:
304 result += estimateMultiPolygon((MultiPolygon) geom);
305 break;
306 case net.postgis.jdbc.geometry.Geometry.GEOMETRYCOLLECTION:
307 result += estimateCollection((GeometryCollection) geom);
308 break;
309 default:
310 throw new IllegalArgumentException("Unknown Geometry Type: " + getWKBType(geom));
311 }
312 return result;
313 }
314
315 private boolean checkSrid(Geometry geom) {
316 final int srid = geom.getSRID();
317 return (srid > 0);
318 }
319
320 private int estimatePoint(Point geom) {
321 return 8 * getCoordDim(geom);
322 }
323
324 /** Write an Array of "full" Geometries */
325 private int estimateGeometryArray(Geometry container) {
326 int result = 0;
327 for (int i = 0; i < container.getNumGeometries(); i++) {
328 result += estimateBytes(container.getGeometryN(i));
329 }
330 return result;
331 }
332
333 /** Estimate an array of "fat" Points */
334 private int estimateMultiPoint(MultiPoint geom) {
335 // int size
336 int result = 4;
337 if (geom.getNumGeometries() > 0) {
338 // We can shortcut here, compared to estimateGeometryArray, as all
339 // subgeoms have the same fixed size
340 result += geom.getNumGeometries() * estimateBytes(geom.getGeometryN(0));
341 }
342 return result;
343 }
344
345 private int estimateLineString(LineString geom) {
346 if (geom == null || geom.getNumGeometries() == 0) {
347 return 0;
348 } else {
349 return 4 + 8 * getCoordSequenceDim(geom.getCoordinateSequence()) * geom.getCoordinateSequence().size();
350 }
351 }
352
353 private int estimatePolygon(Polygon geom) {
354 // int length
355 int result = 4;
356 result += estimateLineString(geom.getExteriorRing());
357 for (int i = 0; i < geom.getNumInteriorRing(); i++) {
358 result += estimateLineString(geom.getInteriorRingN(i));
359 }
360 return result;
361 }
362
363 private int estimateMultiLineString(MultiLineString geom) {
364 // 4-byte count + subgeometries
365 return 4 + estimateGeometryArray(geom);
366 }
367
368 private int estimateMultiPolygon(MultiPolygon geom) {
369 // 4-byte count + subgeometries
370 return 4 + estimateGeometryArray(geom);
371 }
372
373 private int estimateCollection(GeometryCollection geom) {
374 // 4-byte count + subgeometries
375 return 4 + estimateGeometryArray(geom);
376 }
377
378 public static final int getCoordDim(Geometry geom) {
379 if (geom.isEmpty()) {
380 return 0;
381 }
382 if (geom instanceof Point) {
383 return getCoordSequenceDim(((Point) geom).getCoordinateSequence());
384 } else if (geom instanceof LineString) {
385 return getCoordSequenceDim(((LineString) geom).getCoordinateSequence());
386 } else if (geom instanceof Polygon) {
387 return getCoordSequenceDim(((Polygon) geom).getExteriorRing().getCoordinateSequence());
388 } else {
389 return getCoordDim(geom.getGeometryN(0));
390 }
391 }
392
393 public static final int getCoordSequenceDim(CoordinateSequence coords) {
394 if (coords == null || coords.size() == 0)
395 return 0;
396 // JTS has a really strange way to handle dimensions!
397 // Just have a look at PackedCoordinateSequence and
398 // CoordinateArraySequence
399 int dimensions = coords.getDimension();
400 if (dimensions == 3) {
401 // CoordinateArraySequence will always return 3, so we have to
402 // check, if
403 // the third ordinate contains NaN, then the geom is actually
404 // 2-dimensional
405 return Double.isNaN(coords.getOrdinate(0, CoordinateSequence.Z)) ? 2 : 3;
406 } else {
407 return dimensions;
408 }
409 }
410 }
0 /*
1 * JtsGeometry.java
2 *
3 * Wrapper for PostgreSQL JDBC driver to allow transparent reading and writing
4 * of JTS geometries
5 *
6 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
7 *
8 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 *
24 */
25
26 package net.postgis.jdbc.jts;
27
28 import java.sql.SQLException;
29
30 import org.postgresql.util.PGobject;
31
32 import org.locationtech.jts.geom.CoordinateSequenceFactory;
33 import org.locationtech.jts.geom.Geometry;
34 import org.locationtech.jts.geom.GeometryCollection;
35 import org.locationtech.jts.geom.GeometryFactory;
36 import org.locationtech.jts.geom.Polygon;
37 import org.locationtech.jts.geom.PrecisionModel;
38 import org.locationtech.jts.geom.impl.PackedCoordinateSequenceFactory;
39 import org.locationtech.jts.io.WKTReader;
40
41 /**
42 * JTS Geometry SQL wrapper. Supports PostGIS 1.x (lwgeom hexwkb) for writing
43 * and both PostGIS 0.x (EWKT) and 1.x (lwgeom hexwkb) for reading.
44 *
45 * @author Markus Schaber
46 */
47
48 public class JtsGeometry extends PGobject {
49 /* JDK 1.5 Serialization */
50 private static final long serialVersionUID = 0x100;
51
52 Geometry geom;
53
54 final static JtsBinaryParser bp = new JtsBinaryParser();
55
56 final static JtsBinaryWriter bw = new JtsBinaryWriter();
57
58 final static PrecisionModel prec = new PrecisionModel();
59
60 final static CoordinateSequenceFactory csfac = PackedCoordinateSequenceFactory.DOUBLE_FACTORY;
61
62 final static GeometryFactory geofac = new GeometryFactory(prec, 0, csfac);
63
64 static final WKTReader reader = new WKTReader(geofac);
65
66 /** Constructor called by JDBC drivers */
67 public JtsGeometry() {
68 setType("geometry");
69 }
70
71 public JtsGeometry(Geometry geom) {
72 this();
73 this.geom = geom;
74 }
75
76 public JtsGeometry(String value) throws SQLException {
77 this();
78 setValue(value);
79 }
80
81 public void setValue(String value) throws SQLException {
82 geom = geomFromString(value);
83 }
84
85 public static Geometry geomFromString(String value) throws SQLException {
86 try {
87 value = value.trim();
88 if (value.startsWith("00") || value.startsWith("01")) {
89 return bp.parse(value);
90 } else {
91 Geometry result;
92 // no srid := 0 in JTS world
93 int srid = 0;
94 // break up geometry into srid and wkt
95 if (value.startsWith("SRID=")) {
96 String[] temp = value.split(";");
97 value = temp[1].trim();
98 srid = Integer.parseInt(temp[0].substring(5));
99 }
100
101 result = reader.read(value);
102 setSridRecurse(result, srid);
103 return result;
104 }
105 } catch (Exception E) {
106 E.printStackTrace();
107 throw new SQLException("Error parsing SQL data:" + E);
108 }
109 }
110
111
112 /**
113 * Recursively set a srid for the geometry and all subgeometries
114 * @param geom Geometry to work on
115 * @param srid SRID to be set to
116 */
117 public static void setSridRecurse(final Geometry geom, final int srid) {
118 geom.setSRID(srid);
119 if (geom instanceof GeometryCollection) {
120 final int subcnt = geom.getNumGeometries();
121 for (int i = 0; i < subcnt; i++) {
122 setSridRecurse(geom.getGeometryN(i), srid);
123 }
124 } else if (geom instanceof Polygon) {
125 Polygon poly = (Polygon) geom;
126 poly.getExteriorRing().setSRID(srid);
127 final int subcnt = poly.getNumInteriorRing();
128 for (int i = 0; i < subcnt; i++) {
129 poly.getInteriorRingN(i).setSRID(srid);
130 }
131 }
132 }
133
134 public Geometry getGeometry() {
135 return geom;
136 }
137
138 public String toString() {
139 return geom.toString();
140 }
141
142 public String getValue() {
143 return bw.writeHexed(getGeometry());
144 }
145
146 public Object clone() {
147 JtsGeometry obj = new JtsGeometry(geom);
148 obj.setType(type);
149 return obj;
150 }
151
152 public boolean equals(Object obj) {
153 if ((obj != null) && (obj instanceof JtsGeometry)) {
154 Geometry other = ((JtsGeometry) obj).geom;
155 if (this.geom == other) { // handles identity as well as both
156 // ==null
157 return true;
158 } else if (this.geom != null && other != null) {
159 return other.equals(this.geom);
160 }
161 }
162 return false;
163 }
164 }
0 /*
1 * JtsGisWrapper.java
2 *
3 * Allows transparent usage of JTS Geometry classes via PostgreSQL JDBC driver
4 * connected to a PostGIS enabled PostgreSQL server.
5 *
6 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
7 *
8 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 *
24 */
25
26 package net.postgis.jdbc.jts;
27
28 import org.postgresql.Driver;
29 import org.postgresql.PGConnection;
30
31 import java.sql.Connection;
32 import java.sql.SQLException;
33 import java.util.Properties;
34
35 /**
36 * JtsGisWrapper
37 *
38 * Wraps the PostGreSQL Driver to add the JTS/PostGIS Object Classes.
39 *
40 * This method currently works with J2EE DataSource implementations, and with
41 * DriverManager framework.
42 *
43 * Simply replace the "jdbc:postgresql:" with a "jdbc:postgresql_JTS" in the
44 * jdbc URL.
45 *
46 * @author markus.schaber@logix-tt.com
47 *
48 */
49 public class JtsGisWrapper extends Driver {
50
51 private static final String POSTGRES_PROTOCOL = "jdbc:postgresql:";
52 private static final String POSTGIS_PROTOCOL = "jdbc:postgresql_JTS:";
53 public static final String REVISION = "$Revision$";
54
55 public JtsGisWrapper() {
56 super();
57 }
58
59 static {
60 try {
61 // Analogy to org.postgresql.Driver
62 java.sql.DriverManager.registerDriver(new JtsGisWrapper());
63 } catch (SQLException e) {
64 e.printStackTrace();
65 }
66 }
67
68 /**
69 * Creates a postgresql connection, and then adds the PostGIS data types to
70 * it calling addpgtypes()
71 *
72 * @param url the URL of the database to connect to
73 * @param info a list of arbitrary tag/value pairs as connection arguments
74 * @return a connection to the URL or null if it isnt us
75 * @exception SQLException if a database access error occurs
76 *
77 * @see java.sql.Driver#connect
78 * @see org.postgresql.Driver
79 */
80 public java.sql.Connection connect(String url, Properties info) throws SQLException {
81 url = mangleURL(url);
82 Connection result = super.connect(url, info);
83 addGISTypes((PGConnection) result);
84 return result;
85 }
86
87 /**
88 * Adds the JTS/PostGIS Data types to a PG Connection.
89 * @param pgconn The PGConnection object to add the types to
90 * @throws SQLException when an SQLException occurs
91 */
92 public static void addGISTypes(PGConnection pgconn) throws SQLException {
93 pgconn.addDataType("geometry", net.postgis.jdbc.jts.JtsGeometry.class);
94 pgconn.addDataType("box3d", net.postgis.jdbc.PGbox3d.class);
95 pgconn.addDataType("box2d", net.postgis.jdbc.PGbox2d.class);
96 }
97
98 /**
99 * Mangles the PostGIS URL to return the original PostGreSQL URL
100 *
101 * @param url String containing the url to be "mangled"
102 * @return "mangled" string
103 * @throws SQLException when a SQLException occurs
104 */
105 public static String mangleURL(String url) throws SQLException {
106 if (url.startsWith(POSTGIS_PROTOCOL)) {
107 return POSTGRES_PROTOCOL + url.substring(POSTGIS_PROTOCOL.length());
108 } else {
109 throw new SQLException("Unknown protocol or subprotocol in url " + url);
110 }
111 }
112
113 /**
114 * Returns true if the driver thinks it can open a connection to the given
115 * URL. Typically, drivers will return true if they understand the
116 * subprotocol specified in the URL and false if they don't. Our protocols
117 * start with jdbc:postgresql_postGIS:
118 *
119 * @see java.sql.Driver#acceptsURL
120 * @param url the URL of the driver
121 * @return true if this driver accepts the given URL
122 */
123 public boolean acceptsURL(String url) {
124 try {
125 url = mangleURL(url);
126 } catch (SQLException e) {
127 return false;
128 }
129 return super.acceptsURL(url);
130 }
131
132 /**
133 * Gets the underlying drivers major version number
134 *
135 * @return the drivers major version number
136 */
137
138 public int getMajorVersion() {
139 return super.getMajorVersion();
140 }
141
142 /**
143 * Get the underlying drivers minor version number
144 *
145 * @return the drivers minor version number
146 */
147 public int getMinorVersion() {
148 return super.getMinorVersion();
149 }
150
151 /**
152 * Returns our own CVS version plus postgres Version
153 *
154 * @return String representation of the version
155 */
156 public static String getVersion() {
157 return "JtsGisWrapper " + REVISION + ", wrapping " + Driver.getVersion();
158 }
159 }
0 /*
1 * JtsWrapper.java
2 *
3 * Allows transparent usage of JTS Geometry classes via PostgreSQL JDBC driver
4 * connected to a PostGIS enabled PostgreSQL server.
5 *
6 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
7 *
8 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 *
24 */
25
26 package net.postgis.jdbc.jts;
27
28 import java.sql.Connection;
29 import java.sql.SQLException;
30 import java.util.Properties;
31 import java.util.logging.Level;
32 import java.util.logging.Logger;
33
34 import org.postgresql.Driver;
35 import org.postgresql.PGConnection;
36
37 /**
38 * JtsWrapper
39 *
40 * Wraps the PostGreSQL Driver to add the JTS/PostGIS Object Classes.
41 *
42 * This method currently works with J2EE DataSource implementations, and with
43 * DriverManager framework.
44 *
45 * Simply replace the "jdbc:postgresql:" with a "jdbc:postgres_jts:" in the jdbc
46 * URL.
47 *
48 * When using the drivermanager, you need to initialize JtsWrapper instead of
49 * (or in addition to) org.postgresql.Driver. When using a J2EE DataSource
50 * implementation, set the driver class property in the datasource config, the
51 * following works for jboss:
52 *
53 * &lt;driver-class&gt;net.postgis.jdbc.jts.PostGisWrapper&lt;/driver-class&gt;
54 *
55 * @author markus.schaber@logix-tt.com
56 *
57 */
58 public class JtsWrapper extends Driver {
59
60 protected static final Logger logger = Logger.getLogger("net.postgis.jdbc.DriverWrapper");
61
62 private static final String POSTGRES_PROTOCOL = "jdbc:postgresql:";
63 private static final String POSTGIS_PROTOCOL = "jdbc:postgres_jts:";
64 public static final String REVISION = "$Revision$";
65
66 public JtsWrapper() {
67 super();
68 }
69
70 static {
71 try {
72 // Try to register ourself to the DriverManager
73 java.sql.DriverManager.registerDriver(new JtsWrapper());
74 } catch (SQLException e) {
75 logger.log(Level.WARNING, "Error registering PostgreSQL Jts Wrapper Driver", e);
76 }
77 }
78
79 /**
80 * Creates a postgresql connection, and then adds the JTS GIS data types to
81 * it calling addpgtypes()
82 *
83 * @param url the URL of the database to connect to
84 * @param info a list of arbitrary tag/value pairs as connection arguments
85 * @return a connection to the URL or null if it isnt us
86 * @exception SQLException if a database access error occurs
87 *
88 * @see java.sql.Driver#connect
89 * @see org.postgresql.Driver
90 */
91 public java.sql.Connection connect(String url, Properties info) throws SQLException {
92 url = mangleURL(url);
93 Connection result = super.connect(url, info);
94 addGISTypes((PGConnection)result);
95 return result;
96 }
97
98 /**
99 * Adds the JTS/PostGIS Data types to a PG Connection.
100 * @param pgconn The PGConnection object to add the types to
101 * @throws SQLException when an SQLException occurs
102 */
103 public static void addGISTypes(PGConnection pgconn) throws SQLException {
104 pgconn.addDataType("geometry", net.postgis.jdbc.jts.JtsGeometry.class);
105 }
106
107 /**
108 * Mangles the PostGIS URL to return the original PostGreSQL URL
109 *
110 * @param url String containing the url to be "mangled"
111 * @return "mangled" string
112 * @throws SQLException when a SQLException occurs
113 */
114 public static String mangleURL(String url) throws SQLException {
115 if (url.startsWith(POSTGIS_PROTOCOL)) {
116 return POSTGRES_PROTOCOL + url.substring(POSTGIS_PROTOCOL.length());
117 } else {
118 throw new SQLException("Unknown protocol or subprotocol in url " + url);
119 }
120 }
121
122 /**
123 * Check whether the driver thinks he can handle the given URL.
124 *
125 * @see java.sql.Driver#acceptsURL
126 * @param url the URL of the driver
127 * @return true if this driver accepts the given URL
128 */
129 public boolean acceptsURL(String url) {
130 try {
131 url = mangleURL(url);
132 } catch (SQLException e) {
133 return false;
134 }
135 return super.acceptsURL(url);
136 }
137
138 /**
139 * Gets the underlying drivers major version number
140 *
141 * @return the drivers major version number
142 */
143
144 public int getMajorVersion() {
145 return super.getMajorVersion();
146 }
147
148 /**
149 * Get the underlying drivers minor version number
150 *
151 * @return the drivers minor version number
152 */
153 public int getMinorVersion() {
154 return super.getMinorVersion();
155 }
156
157 /**
158 * Returns our own CVS version plus postgres Version
159 *
160 * @return String representation of the version
161 */
162 public static String getVersion() {
163 return "JtsGisWrapper " + REVISION + ", wrapping " + Driver.getVersion();
164 }
165 }
0 <body><p>Parser between JTS and PostGIS geometry formats.</p></body>
0 /*
1 * JtsParserTest.java
2 *
3 * JtsParserTest for JTS - relies on net.postgis V1.0.0+ package.
4 *
5 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 *
21 */
22
23 package net.postgis.jdbc.jts;
24
25
26 import net.postgis.jdbc.geometry.binary.ValueSetter;
27
28 import org.locationtech.jts.geom.*;
29 import net.postgis.tools.testutils.TestContainerController;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32 import org.testng.Assert;
33 import org.testng.ITestContext;
34 import org.testng.annotations.AfterClass;
35 import org.testng.annotations.BeforeClass;
36 import org.testng.annotations.Test;
37
38 import java.sql.*;
39
40
41 /**
42 * JtsParseTest
43 *
44 * This test class was adapted from the {@code JtsTestParsr} example standalone class.
45 * It is meant to be run in standalone mode or run against a PostGIS database, but it will need to be
46 * fixed to run against a PostGIS database as it currently fails in some places with an error:
47 * {@literal function asewkb(geometry) does not exist}
48 */
49 public class JtsParserTest {
50
51 private static final Logger logger = LoggerFactory.getLogger(JtsParserTest.class);
52
53 private static final String JTS_WRAPPER_CLASS_NAME = "net.postgis.jdbc.jts.JtsWrapper";
54
55 /** The srid we use for the srid tests */
56 public static final int SRID = 4326;
57
58 /** The string prefix we get for the srid tests */
59 public static final String SRIDPREFIX = "SRID=" + SRID + ";";
60
61 /**
62 * Our set of geometries to test.
63 */
64 public static final String ALL = "ALL";
65 public static final String ONLY10 = "ONLY10";
66 public static final String EQUAL10 = "EQUAL10";
67 public static final String[][] testset = new String[][] {
68 { ALL, // 2D
69 "POINT(10 10)" },
70 { ALL, // 3D with 3rd coordinate set to 0
71 "POINT(10 10 0)" },
72 { ALL, // 3D
73 "POINT(10 10 20)" },
74 { ALL, "MULTIPOINT(11 12, 20 20)" },
75 { ALL, "MULTIPOINT(11 12 13, 20 20 20)" },
76 { ALL, "LINESTRING(10 10,20 20,50 50,34 34)" },
77 { ALL, "LINESTRING(10 10 20,20 20 20,50 50 50,34 34 34)" },
78 { ALL, "POLYGON((10 10,20 10,20 20,20 10,10 10),(5 5,5 6,6 6,6 5,5 5))" },
79 { ALL, "POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))" },
80 {
81 ALL,
82 "MULTIPOLYGON(((10 10,20 10,20 20,20 10,10 10),(5 5,5 6,6 6,6 5,5 5)),((10 10,20 10,20 20,20 10,10 10),(5 5,5 6,6 6,6 5,5 5)))" },
83 {
84 ALL,
85 "MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))" },
86 { ALL, "MULTILINESTRING((10 10,20 10,20 20,20 10,10 10),(5 5,5 6,6 6,6 5,5 5))" },
87 { ALL, "MULTILINESTRING((10 10 5,20 10 5,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))" },
88 { ALL, "GEOMETRYCOLLECTION(POINT(10 10),POINT(20 20))" },
89 { ALL, "GEOMETRYCOLLECTION(POINT(10 10 20),POINT(20 20 20))" },
90 {
91 ALL,
92 "GEOMETRYCOLLECTION(LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34),LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34))" },
93 {
94 ALL,
95 "GEOMETRYCOLLECTION(POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))" },
96 { ONLY10, // Cannot be parsed by 0.X servers
97 "GEOMETRYCOLLECTION(MULTIPOINT(10 10 10, 20 20 20),MULTIPOINT(10 10 10, 20 20 20))" },
98 { EQUAL10, // PostGIs 0.X "flattens" this geometry, so it is not
99 // equal after reparsing.
100 "GEOMETRYCOLLECTION(MULTILINESTRING((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))" },
101 { EQUAL10,// PostGIs 0.X "flattens" this geometry, so it is not
102 // equal
103 // after reparsing.
104 "GEOMETRYCOLLECTION(MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))),MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))))" },
105 {
106 ALL,
107 "GEOMETRYCOLLECTION(POINT(10 10 20),LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34),POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))" },
108 { ONLY10, // Collections that contain both X and MultiX do not
109 // work on
110 // PostGIS 0.x
111 "GEOMETRYCOLLECTION(POINT(10 10 20),MULTIPOINT(10 10 10, 20 20 20),LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34),POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))),MULTILINESTRING((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))" },
112 { ALL,// new (correct) representation
113 "GEOMETRYCOLLECTION EMPTY" },
114 };
115
116 private static JtsBinaryParser jtsBinaryParser = new JtsBinaryParser();
117
118 private static final JtsBinaryWriter jtsBinaryWriter = new JtsBinaryWriter();
119
120 private Connection connection = null;
121
122 private Statement statement = null;
123
124
125 @Test
126 public void test() throws Exception {
127 for (String[] aTestset : testset) {
128 test(aTestset[1], aTestset[0]);
129 test(SRIDPREFIX + aTestset[1], aTestset[0]);
130 }
131 }
132
133
134 public void test(String WKT, String flags) throws SQLException {
135 logger.debug("Original: {}", WKT);
136 Geometry geom = JtsGeometry.geomFromString(WKT);
137 String parsed = geom.toString();
138 if (WKT.startsWith("SRID=")) {
139 parsed = "SRID=" + geom.getSRID() + ";" + parsed;
140 }
141 logger.debug("Parsed: {}", parsed);
142 Geometry regeom = JtsGeometry.geomFromString(parsed);
143 String reparsed = regeom.toString();
144 if (WKT.startsWith("SRID=")) {
145 reparsed = "SRID=" + geom.getSRID() + ";" + reparsed;
146 }
147 logger.debug("Re-Parsed: {}", reparsed);
148 Assert.assertEquals(geom, regeom, "Geometries are not equal");
149 Assert.assertEquals(geom.getSRID(), regeom.getSRID(), "Geometry SRIDs are not equal");
150 Assert.assertEquals(reparsed, parsed, "Text Reps are not equal");
151
152 String hexNWKT = jtsBinaryWriter.writeHexed(geom, ValueSetter.NDR.NUMBER);
153 logger.debug("NDRHex: {}", hexNWKT);
154 regeom = JtsGeometry.geomFromString(hexNWKT);
155 logger.debug("ReNDRHex: {}", regeom);
156 Assert.assertEquals(geom, regeom, "Geometries are not equal");
157
158 String hexXWKT = jtsBinaryWriter.writeHexed(geom, ValueSetter.XDR.NUMBER);
159 logger.debug("XDRHex: {}", hexXWKT);
160 regeom = JtsGeometry.geomFromString(hexXWKT);
161 logger.debug("ReXDRHex: {}", regeom);
162 Assert.assertEquals(geom, regeom, "Geometries are not equal");
163
164 byte[] NWKT = jtsBinaryWriter.writeBinary(geom, ValueSetter.NDR.NUMBER);
165 regeom = jtsBinaryParser.parse(NWKT);
166 logger.debug("NDR: {}", regeom);
167 Assert.assertEquals(geom, regeom, "Geometries are not equal");
168
169 byte[] XWKT = jtsBinaryWriter.writeBinary(geom, ValueSetter.XDR.NUMBER);
170 regeom = jtsBinaryParser.parse(XWKT);
171 logger.debug("XDR: {}", regeom);
172 Assert.assertEquals(geom, regeom, "Geometries are not equal");
173
174 Geometry coordArrayGeom = rebuildCS(geom);
175 logger.debug("CoordArray: {}", regeom);
176 Assert.assertEquals(geom, coordArrayGeom, "Geometries are not equal");
177
178 String coordArrayWKT = jtsBinaryWriter.writeHexed(coordArrayGeom, ValueSetter.NDR.NUMBER);
179 logger.debug("HexCArray: {}", coordArrayWKT);
180 Assert.assertEquals(coordArrayWKT, hexNWKT, "CoordArray HexWKT is not equal");
181
182 int serverPostgisMajor = getPostgisMajor();
183
184 if ((flags.equals(ONLY10)) && serverPostgisMajor < 1) {
185 logger.info("PostGIS server too old, skipping test on connection {}", connection.getCatalog());
186 } else {
187 logger.debug("Testing on connection {}", connection.getCatalog());
188
189 Geometry sqlGeom = viaSQL(WKT, statement);
190 logger.debug("SQLin: {}", sqlGeom.toString());
191 if (!geom.equalsExact(sqlGeom)) {
192 logger.warn("Geometries after SQL are not equal");
193 if (flags.equals(EQUAL10) && serverPostgisMajor < 1) {
194 logger.info("This is expected with PostGIS {}.X", serverPostgisMajor);
195 } else {
196 Assert.fail();
197 }
198 }
199
200 Geometry sqlreGeom = viaSQL(parsed, statement);
201 logger.debug("SQLout: {}", sqlreGeom);
202 if (!geom.equalsExact(sqlreGeom)) {
203 logger.warn("Reparsed Geometries after SQL are not equal");
204 if (flags.equals(EQUAL10) && serverPostgisMajor < 1) {
205 logger.info("This is expected with PostGIS {}.X", serverPostgisMajor);
206 } else {
207 Assert.fail();
208 }
209 }
210
211 sqlreGeom = viaPrepSQL(geom, connection);
212 logger.debug("Prepared: {}", sqlreGeom);
213 if (!geom.equalsExact(sqlreGeom)) {
214 logger.debug("Reparsed Geometries after prepared StatementSQL are not equal");
215 if (flags.equals(EQUAL10) && serverPostgisMajor < 1) {
216 logger.info("This is expected with PostGIS {}.X", serverPostgisMajor);
217 } else {
218 Assert.fail();
219 }
220 }
221
222 // asEWKT() function is not present on PostGIS 0.X, and the test
223 // is pointless as 0.X uses EWKT as canonical rep so the same
224 // functionality was already tested above.
225 if (serverPostgisMajor >= 1) {
226 sqlGeom = ewktViaSQL(WKT, statement);
227 logger.debug("asEWKT: {}", sqlGeom);
228 Assert.assertEquals(geom, sqlGeom);
229
230 sqlGeom = ewkbViaSQL(WKT, statement);
231 logger.debug("asEWKB: {}", sqlGeom);
232 Assert.assertEquals(geom, sqlGeom);
233
234 sqlGeom = viaSQL(hexNWKT, statement);
235 logger.debug("hexNWKT: {}", sqlGeom);
236 Assert.assertEquals(geom, sqlGeom);
237
238 sqlGeom = viaSQL(hexXWKT, statement);
239 logger.debug("hexXWKT: {}", sqlGeom);
240 Assert.assertEquals(geom, sqlGeom);
241
242 sqlGeom = binaryViaSQL(NWKT, connection);
243 logger.debug("NWKT: {}", sqlGeom);
244 Assert.assertEquals(geom, sqlGeom);
245
246 sqlGeom = binaryViaSQL(XWKT, connection);
247 logger.debug("XWKT: {}", sqlGeom);
248 Assert.assertEquals(geom, sqlGeom);
249 }
250 }
251 }
252
253
254 /** Pass a geometry representation through the SQL server */
255 private static Geometry viaSQL(String rep, Statement stat) throws SQLException {
256 ResultSet rs = stat.executeQuery("SELECT geometry_in('" + rep + "')");
257 rs.next();
258 return ((JtsGeometry) rs.getObject(1)).getGeometry();
259 }
260
261
262 /**
263 * Pass a geometry representation through the SQL server via prepared
264 * statement
265 */
266 private static Geometry viaPrepSQL(Geometry geom, Connection conn) throws SQLException {
267 PreparedStatement prep = conn.prepareStatement("SELECT ?::geometry");
268 JtsGeometry wrapper = new JtsGeometry(geom);
269 prep.setObject(1, wrapper, Types.OTHER);
270 ResultSet rs = prep.executeQuery();
271 rs.next();
272 JtsGeometry resultwrapper = ((JtsGeometry) rs.getObject(1));
273 return resultwrapper.getGeometry();
274 }
275
276
277 /** Pass a geometry representation through the SQL server via EWKT */
278 private static Geometry ewktViaSQL(String rep, Statement stat) throws SQLException {
279 ResultSet rs = stat.executeQuery("SELECT ST_AsEWKT(geometry_in('" + rep + "'))");
280 rs.next();
281 String resrep = rs.getString(1);
282 return JtsGeometry.geomFromString(resrep);
283 }
284
285
286 /** Pass a geometry representation through the SQL server via EWKB */
287 private static Geometry ewkbViaSQL(String rep, Statement stat) throws SQLException {
288 ResultSet rs = stat.executeQuery("SELECT ST_AsEWKB(geometry_in('" + rep + "'))");
289 rs.next();
290 byte[] resrep = rs.getBytes(1);
291 return jtsBinaryParser.parse(resrep);
292 }
293
294
295 /** Pass a EWKB geometry representation through the server */
296 private static Geometry binaryViaSQL(byte[] rep, Connection conn) throws SQLException {
297 PreparedStatement prep = conn.prepareStatement("SELECT ?::bytea::geometry");
298 prep.setBytes(1, rep);
299 ResultSet rs = prep.executeQuery();
300 rs.next();
301 JtsGeometry resultwrapper = ((JtsGeometry) rs.getObject(1));
302 return resultwrapper.getGeometry();
303 }
304
305
306 // Rebuild given Geometry with a CoordinateArraySequence implementation.
307 public static Geometry rebuildCS(Geometry geom) {
308 if (geom instanceof Point) {
309 return rebuildCSPoint((Point)geom);
310 } else if (geom instanceof MultiPoint) {
311 return rebuildCSMP((MultiPoint)geom);
312 } else if (geom instanceof LineString) {
313 return rebuildCSLS((LineString)geom);
314 } else if (geom instanceof MultiLineString) {
315 return rebuildCSMLS((MultiLineString)geom);
316 } else if (geom instanceof Polygon) {
317 return rebuildCSP((Polygon)geom);
318 } else if (geom instanceof MultiPolygon) {
319 return rebuildCSMP((MultiPolygon)geom);
320 } else if (geom instanceof GeometryCollection) {
321 return rebuildCSGC((GeometryCollection)geom);
322 } else {
323 throw new AssertionError();
324 }
325 }
326
327
328 private static Point rebuildCSPoint(Point point) {
329 Point result = point.getFactory().createPoint(point.getCoordinate());
330 result.setSRID(point.getSRID());
331 return result;
332 }
333
334
335 private static MultiPoint rebuildCSMP(MultiPoint mp) {
336 Point[] points = new Point[mp.getNumGeometries()];
337 for (int i=0; i < points.length; i++) {
338 points[i] = rebuildCSPoint((Point) mp.getGeometryN(i));
339 }
340 MultiPoint result = mp.getFactory().createMultiPoint(points);
341 result.setSRID(mp.getSRID());
342 return result;
343 }
344
345
346 private static MultiPolygon rebuildCSMP(MultiPolygon multipoly) {
347 Polygon[] polygons = new Polygon[multipoly.getNumGeometries()];
348 for (int i=0; i < polygons.length; i++) {
349 polygons[i] = rebuildCSP((Polygon)multipoly.getGeometryN(i));
350 }
351 MultiPolygon result = multipoly.getFactory().createMultiPolygon(polygons);
352 result.setSRID(multipoly.getSRID());
353 return result;
354 }
355
356
357 private static LineString rebuildCSLS(LineString line) {
358 LineString result = line.getFactory().createLineString(line.getCoordinates());
359 result.setSRID(line.getSRID());
360 return result;
361 }
362
363
364 private static MultiLineString rebuildCSMLS(MultiLineString multiline) {
365 LineString[] polygons = new LineString[multiline.getNumGeometries()];
366 for (int i=0; i < polygons.length; i++) {
367 polygons[i] = rebuildCSLS((LineString)multiline.getGeometryN(i));
368 }
369 MultiLineString result = multiline.getFactory().createMultiLineString(polygons);
370 result.setSRID(multiline.getSRID());
371 return result;
372
373 }
374
375
376 private static Polygon rebuildCSP(Polygon polygon) {
377 LinearRing outer = rebuildLR(polygon.getExteriorRing());
378 LinearRing[] holes = new LinearRing[polygon.getNumInteriorRing()];
379 for (int i=0; i < holes.length; i++) {
380 holes[i] = rebuildLR(polygon.getInteriorRingN(i));
381 }
382 Polygon result = polygon.getFactory().createPolygon(outer, holes);
383 result.setSRID(polygon.getSRID());
384 return result;
385 }
386
387
388 private static LinearRing rebuildLR(LineString ring) {
389 LinearRing result = ring.getFactory().createLinearRing(ring.getCoordinates());
390 result.setSRID(ring.getSRID());
391 return result;
392 }
393
394
395 private static Geometry rebuildCSGC(GeometryCollection coll) {
396 Geometry[] geoms = new Geometry[coll.getNumGeometries()];
397 for (int i = 0; i < coll.getNumGeometries(); i++) {
398 geoms[i] = rebuildCS(coll.getGeometryN(i));
399 }
400 Geometry result = coll.getFactory().createGeometryCollection(geoms);
401 result.setSRID(coll.getSRID());
402 return result;
403 }
404
405
406 public int getPostgisMajor() throws SQLException {
407 ResultSet resultSet = statement.executeQuery("SELECT postgis_version()");
408 resultSet.next();
409 String version = resultSet.getString(1);
410 if (version == null) {
411 throw new SQLException("postgis_version returned NULL!");
412 }
413 version = version.trim();
414 int idx = version.indexOf('.');
415 return Integer.parseInt(version.substring(0, idx));
416 }
417
418
419 @BeforeClass
420 public void initJdbcConnection(ITestContext ctx) throws Exception {
421 final String jdbcUrlSuffix = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_JDBC_URL_SUFFIX);
422 Assert.assertNotNull(jdbcUrlSuffix);
423 final String jdbcUrl = "jdbc:postgres_jts" + jdbcUrlSuffix;
424 final String jdbcUsername = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_USER_PARAM_NAME);
425 Assert.assertNotNull(jdbcUsername);
426 final String jdbcPassword = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_PW_PARAM_NAME);
427 Assert.assertNotNull(jdbcPassword);
428 Class.forName(JTS_WRAPPER_CLASS_NAME);
429 connection = DriverManager.getConnection(jdbcUrl, jdbcUsername, jdbcPassword);
430 statement = connection.createStatement();
431 }
432
433
434 @AfterClass
435 public void unallocateDatabaseResources() throws Exception {
436 if ((statement != null) && (!statement.isClosed())) {
437 statement.close();
438 }
439 if ((connection != null) && (!connection.isClosed())) {
440 connection.close();
441 }
442 }
443
444
445 }
0 <configuration debug="false">
1
2 <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
3 <layout class="ch.qos.logback.classic.PatternLayout">
4 <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
5 </layout>
6 </appender>
7
8 <root level="debug">
9 <appender-ref ref="STDOUT" />
10 </root>
11
12 <logger name="com.github.dockerjava" level="ERROR"/>
13 <logger name="org.testcontainers" level="ERROR"/>
14 <logger name="net.postgis" level="ERROR"/>
15
16 <logger name="net.postgis.jdbc.jts" level="ERROR"/>
17
18 </configuration>
0 <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
1 <suite name="JTS Parser Integration Test Suite" verbose="1">
2
3 <parameter name="test.container.image-name" value="${test.container.image}"/>
4 <parameter name="test.container.port" value="${test.db.port}"/>
5 <parameter name="test.container.env.user" value="${test.db.username}"/>
6 <parameter name="test.container.env.password" value="${test.db.password}"/>
7 <parameter name="test.container.env.db" value="${test.db.name}"/>
8
9 <test name="JTS Parser Integration Tests">
10 <classes>
11 <class name="net.postgis.tools.testutils.TestContainerController"/>
12 <class name="net.postgis.jdbc.jts.JtsParserTest"/>
13 </classes>
14 </test>
15
16 </suite>
+0
-1
tools/osgeo-postgis-jdbc-test-util/.gitignore less more
0 dependency-reduced-pom.xml
+0
-114
tools/osgeo-postgis-jdbc-test-util/pom.xml less more
0 <?xml version="1.0" encoding="UTF-8"?>
1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
2 <modelVersion>4.0.0</modelVersion>
3
4 <parent>
5 <artifactId>tools</artifactId>
6 <groupId>net.postgis</groupId>
7 <version>2.5.0</version>
8 </parent>
9
10 <artifactId>osgeo-postgis-jdbc-test-util</artifactId>
11 <version>2.5.0</version>
12 <packaging>jar</packaging>
13
14 <name>osgeo-postgis-jdbc-test-util</name>
15 <description>
16 Simple smoke test util for verifying functionality postgis jdbc jar against a postgresql database with posgis
17 extensions on OSGeo-Live.
18 </description>
19
20 <properties>
21 <testTablePrefix>SMOKE_TEST</testTablePrefix>
22 </properties>
23
24 <dependencies>
25 <dependency>
26 <groupId>net.postgis</groupId>
27 <artifactId>postgis-jdbc</artifactId>
28 <version>2.5.0</version>
29 </dependency>
30 <dependency>
31 <groupId>ch.qos.logback</groupId>
32 <artifactId>logback-classic</artifactId>
33 <version>${dependency.logback.version}</version>
34 </dependency>
35 <dependency>
36 <groupId>ch.qos.logback</groupId>
37 <artifactId>logback-core</artifactId>
38 <version>${dependency.logback.version}</version>
39 </dependency>
40 <dependency>
41 <groupId>net.postgis.tools</groupId>
42 <artifactId>test-utils</artifactId>
43 <version>2.5.0</version>
44 <scope>test</scope>
45 </dependency>
46 </dependencies>
47
48 <build>
49 <testResources>
50 <testResource>
51 <directory>src/test/resources</directory>
52 </testResource>
53 <testResource>
54 <directory>src/test/resources-filtered</directory>
55 <filtering>true</filtering>
56 </testResource>
57 </testResources>
58 <plugins>
59 <plugin>
60 <groupId>org.apache.maven.plugins</groupId>
61 <artifactId>maven-failsafe-plugin</artifactId>
62 <executions>
63 <execution>
64 <id>integration-tests</id>
65 <goals>
66 <goal>integration-test</goal>
67 <goal>verify</goal>
68 </goals>
69 <configuration>
70 <skip>${maven.integration.test.skip}</skip>
71 <suiteXmlFiles>
72 <suiteXmlFile>${project.build.testOutputDirectory}/testng-it.xml</suiteXmlFile>
73 </suiteXmlFiles>
74 </configuration>
75 </execution>
76 </executions>
77 </plugin>
78 <plugin>
79 <groupId>org.apache.maven.plugins</groupId>
80 <artifactId>maven-shade-plugin</artifactId>
81 <executions>
82 <execution>
83 <id>shade</id>
84 <phase>package</phase>
85 <goals>
86 <goal>shade</goal>
87 </goals>
88 <configuration>
89 <artifactSet>
90 <excludes>
91 <exclude>net.postgis:postgis-jdbc</exclude>
92 </excludes>
93 </artifactSet>
94 <transformers>
95 <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
96 <mainClass>net.postgis.osgeo.util.Main</mainClass>
97 </transformer>
98 </transformers>
99 </configuration>
100 </execution>
101 </executions>
102 </plugin>
103 <plugin>
104 <groupId>org.apache.maven.plugins</groupId>
105 <artifactId>maven-surefire-plugin</artifactId>
106 <configuration>
107 <skip>true</skip>
108 </configuration>
109 </plugin>
110 </plugins>
111 </build>
112
113 </project>
+0
-236
tools/osgeo-postgis-jdbc-test-util/src/main/java/net/postgis/osgeo/util/Main.java less more
0 package net.postgis.osgeo.util;
1
2 import org.postgis.PGbox3d;
3 import org.postgis.PGgeometry;
4 import org.slf4j.Logger;
5 import org.slf4j.LoggerFactory;
6
7 import java.sql.Connection;
8 import java.sql.DatabaseMetaData;
9 import java.sql.DriverManager;
10 import java.sql.ResultSet;
11 import java.sql.SQLException;
12 import java.sql.Statement;
13 import java.util.Objects;
14 import java.util.UUID;
15
16
17 /**
18 * Simple smoke test util for verifying functionality postgis jdbc jar against a postgresql database
19 * with posgis extensions on OSGeo-Live.
20 *
21 * @author Phillip Ross
22 */
23 public class Main {
24
25 private static final Logger logger = LoggerFactory.getLogger(Main.class);
26
27 private static final String DEFAULT_TEST_TABLE_PREFIX = "SMOKE_TEST";
28
29 private static final String JDBC_DRIVER_CLASS_NAME = "org.postgresql.Driver";
30
31 private Connection connection = null;
32
33 private Statement statement = null;
34
35 private String testTableName = null;
36
37
38 public Main(final String jdbcUrl,
39 final String jdbcUsername,
40 final String jdbcPassword,
41 final String testTablePrefix) {
42 try {
43 Objects.requireNonNull(jdbcUrl, "A JDBC URL must be specified");
44 Objects.requireNonNull(jdbcUsername, "A database username must be specified.");
45 Objects.requireNonNull(jdbcPassword, "A database password must be specified.");
46 Objects.requireNonNull(testTablePrefix, "Unable to determine test table prefix");
47 logger.debug("Running test (url/u/p/ttp): {}/{}/{}/{}", jdbcUrl, jdbcUsername, jdbcPassword, testTablePrefix);
48 setupDatabaseResources(jdbcUrl, jdbcUsername, jdbcPassword);
49 Objects.requireNonNull(connection, "Unable to continue testing without a connection to the database");
50 if (testDatatypeRegistration()) {
51 Objects.requireNonNull(statement, "Unable to continue testing without a statement resource");
52 if (createTestTable(testTablePrefix)) {
53 if (testSQL()) {
54 logger.debug("All tests passed");
55 dropTestTable();
56 }
57 }
58 }
59 closeDatabaseResources();
60 } catch (Exception e) {
61 logger.error("Caught exception: {} {}", e.getClass().getName(), e.getMessage());
62 e.printStackTrace();
63 }
64 }
65
66
67 private boolean testSQL() {
68 final String insertPointSQL = "insert into " + testTableName + " values ('POINT (10 10 10)',1)";
69 final String insertPolygonSQL = "insert into " + testTableName + " values ('POLYGON ((0 0 0,0 10 0,10 10 0,10 0 0,0 0 0))',2)";
70
71 boolean testPass = false;
72 try {
73 logger.debug("Inserting point...");
74 statement.execute(insertPointSQL);
75
76 logger.debug("Inserting polygon...");
77 statement.execute(insertPolygonSQL);
78
79 logger.debug("Querying table...");
80 ResultSet resultSet = statement.executeQuery("select ST_AsText(geom),id from " + testTableName);
81 while (resultSet.next()) {
82 Object obj = resultSet.getObject(1);
83 int id = resultSet.getInt(2);
84 logger.debug("Row {}: {}", id, obj.toString());
85 }
86 testPass = true;
87 } catch (SQLException se) {
88 logger.error(
89 "Caught SQLException attempting to issue SQL to the database: {} {}",
90 se.getClass().getName(),
91 se.getMessage()
92 );
93 }
94 return testPass;
95 }
96
97
98 private boolean createTestTable(final String testTablePrefix) {
99 testTableName = testTablePrefix + "_" + UUID.randomUUID().toString().replaceAll("-", "");
100 final String dropSQL = "drop table " + testTableName;
101 final String createSQL = "create table " + testTableName + " (geom geometry, id int4)";
102
103 boolean testPass = false;
104 logger.debug("Creating table with geometric types...");
105 boolean tableExists = false;
106 try {
107 DatabaseMetaData databaseMetaData = connection.getMetaData();
108 try (ResultSet resultSet = databaseMetaData.getTables(null, null, testTableName.toLowerCase(), new String[] {"TABLE"})) {
109 while (resultSet.next()) {
110 tableExists = true;
111 }
112 }
113 if (tableExists) {
114 statement.execute(dropSQL);
115 }
116 statement.execute(createSQL);
117 testPass = true;
118 } catch (SQLException se) {
119 logger.error(
120 "Caught SQLException attempting to create the test table: {} {}",
121 se.getClass().getName(),
122 se.getMessage()
123 );
124 }
125 return testPass;
126 }
127
128
129 private void dropTestTable() {
130 final String dropSQL = "drop table " + testTableName;
131 logger.debug("Dropping test table");
132 boolean tableExists = false;
133 try {
134 DatabaseMetaData databaseMetaData = connection.getMetaData();
135 try (ResultSet resultSet = databaseMetaData.getTables(null, null, testTableName.toLowerCase(), new String[] {"TABLE"})) {
136 while (resultSet.next()) {
137 tableExists = true;
138 }
139 }
140 if (tableExists) {
141 statement.execute(dropSQL);
142 }
143 } catch (SQLException se) {
144 logger.error(
145 "Caught SQLException attempting to drop the test table: {} {}",
146 se.getClass().getName(),
147 se.getMessage()
148 );
149 }
150 }
151
152
153 private boolean testDatatypeRegistration() {
154 boolean testPass = false;
155 logger.debug("Adding geometric type entries...");
156 try {
157 ((org.postgresql.PGConnection)connection).addDataType("geometry", PGgeometry.class);
158 ((org.postgresql.PGConnection)connection).addDataType("box3d", PGbox3d.class);
159 testPass = true;
160 } catch (SQLException se) {
161 logger.error(
162 "Caught SQLException attempting to register datatypes with PostgreSQL driver: {} {}",
163 se.getClass().getName(),
164 se.getMessage()
165 );
166 }
167 return testPass;
168 }
169
170
171 private void closeDatabaseResources() {
172 try {
173 if (statement != null) {
174 statement.close();
175 }
176 } catch (SQLException se) {
177 logger.error(
178 "Caught SQLException attempting to close statement resource: {} {}",
179 se.getClass().getName(),
180 se.getMessage()
181 );
182 }
183 try {
184 if (connection != null) {
185 connection.close();
186 }
187 } catch (SQLException se) {
188 logger.error(
189 "Caught SQLException attempting to close connection to the database: {} {}",
190 se.getClass().getName(),
191 se.getMessage()
192 );
193 }
194 }
195
196
197 private void setupDatabaseResources(final String url, final String username, final String password) {
198 try {
199 Class.forName(JDBC_DRIVER_CLASS_NAME);
200 } catch (ClassNotFoundException e) {
201 logger.error("Caught exception attempting to load jdbc driver class {}", JDBC_DRIVER_CLASS_NAME);
202 logger.error("Check your classpath to verify that you've included the postgresql jdbc driver.");
203 }
204 try {
205 connection = DriverManager.getConnection(url, username, password);
206 statement = connection.createStatement();
207 } catch (SQLException se) {
208 logger.error(
209 "Caught SQLException attempting to setup database resources: {} {}",
210 se.getClass().getName(),
211 se.getMessage()
212 );
213 }
214 }
215
216
217 public static void main(final String[] args) {
218 if (args.length < 3) {
219 System.out.println("parameters: jdbcUrl jdbcUsername jdbcPassword [testTablePrefix]");
220 } else {
221 String jdbcUrl = args[0];
222 String jdbcUsername = args[1];
223 String jdbcPassword = args[2];
224 String testTablePrefix = DEFAULT_TEST_TABLE_PREFIX;
225 if (args.length > 3) {
226 testTablePrefix = args[3];
227 }
228 new Main(jdbcUrl, jdbcUsername, jdbcPassword, testTablePrefix);
229 }
230 }
231
232
233 }
234
235 // java -classpath ~/.m2/repository/net/postgis/postgis-jdbc/2.2.1-SNAPSHOT/postgis-jdbc-2.2.1-SNAPSHOT.jar:target/osgeo-postgis-jdbc-test-util-0.0.1-SNAPSHOT.jar net.postgis.osgeo.util.Main jdbc:postgresql://db01:5432/postgis1 postgis1 postgis1 smoke_test
+0
-24
tools/osgeo-postgis-jdbc-test-util/src/main/scripts/test.sh less more
0 #!/usr/bin/env bash
1
2 # The following sets variables based in command arguments
3 TEST_JAR="${1}" # This should be the postgis-jdbc jar file to be tested.
4 DB_HOSTNAME_AND_PORT=${2} # This should be the hostname:port of the database
5 DB_USERNAME=${3} # This should be the database user to login as.
6 DB_PASSWORD=${4} # This should be the database password to be used during login.
7
8 # The following can be changed to point to the jar containing the test utility. By default it
9 # points to a jar file in a local maven repository.
10 MVN_REPO_LOCATION=~/.m2/repository
11 GROUP_ID_DIR=/net/postgis
12 TEST_UTIL_JAR=${MVN_REPO_LOCATION}${GROUP_ID_DIR}/osgeo-postgis-jdbc-test-util/0.0.1-SNAPSHOT/osgeo-postgis-jdbc-test-util-0.0.1-SNAPSHOT.jar
13
14 # The following variables are derived from the variables above.
15 # They are used to invoke the JVM with the test utility.
16 JDBC_URL="jdbc:postgresql://${DB_HOSTNAME_AND_PORT}/postgis1"
17 JDBC_USERNAME=${DB_USERNAME}
18 JDBC_PASSWORD=${DB_PASSWORD}
19
20 # The exactly commandline used to invoke the utility is output before it is actually invoked.
21 echo "==> java -classpath ${TEST_JAR}:${TEST_UTIL_JAR} net.postgis.osgeo.util.Main ${JDBC_URL} ${JDBC_USERNAME} ${JDBC_PASSWORD}"
22
23 java -classpath ${TEST_JAR}:${TEST_UTIL_JAR} net.postgis.osgeo.util.Main ${JDBC_URL} ${JDBC_USERNAME} ${JDBC_PASSWORD}
+0
-33
tools/osgeo-postgis-jdbc-test-util/src/test/java/net/postgis/osgeo/util/UtilTest.java less more
0 package net.postgis.osgeo.util;
1
2 import net.postgis.tools.testutils.TestContainerController;
3 import org.slf4j.Logger;
4 import org.slf4j.LoggerFactory;
5 import org.testng.Assert;
6 import org.testng.ITestContext;
7 import org.testng.annotations.Test;
8
9
10 /**
11 * A test class for testing the primary utility.
12 *
13 * @author Phillip Ross
14 */
15 public class UtilTest {
16
17 private static final Logger logger = LoggerFactory.getLogger(UtilTest.class);
18
19
20 @Test
21 public void test(ITestContext ctx) {
22 final String jdbcUrlSuffix = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_JDBC_URL_SUFFIX);
23 Assert.assertNotNull(jdbcUrlSuffix);
24 final String jdbcUrl = "jdbc:postgresql" + jdbcUrlSuffix;
25 final String jdbcUsername = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_USER_PARAM_NAME);
26 Assert.assertNotNull(jdbcUsername);
27 final String jdbcPassword = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_PW_PARAM_NAME);
28 Main.main(new String[] {jdbcUrl, jdbcUsername, jdbcPassword});
29 }
30
31
32 }
+0
-19
tools/osgeo-postgis-jdbc-test-util/src/test/resources/logback-test.xml less more
0 <configuration debug="false">
1
2 <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
3 <layout class="ch.qos.logback.classic.PatternLayout">
4 <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
5 </layout>
6 </appender>
7
8 <root level="debug">
9 <appender-ref ref="STDOUT" />
10 </root>
11
12 <logger name="com.github.dockerjava" level="ERROR"/>
13 <logger name="org.testcontainers" level="ERROR"/>
14 <logger name="net.postgis" level="ERROR"/>
15
16 <logger name="net.postgis.osgeo.util" level="DEBUG"/>
17
18 </configuration>
+0
-17
tools/osgeo-postgis-jdbc-test-util/src/test/resources-filtered/testng-it.xml less more
0 <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
1 <suite name="OSGeo PostGIS JDBC Test Util Test Suite" verbose="1">
2
3 <parameter name="test.container.image-name" value="${test.container.image}"/>
4 <parameter name="test.container.port" value="${test.db.port}"/>
5 <parameter name="test.container.env.user" value="${test.db.username}"/>
6 <parameter name="test.container.env.password" value="${test.db.password}"/>
7 <parameter name="test.container.env.db" value="${test.db.name}"/>
8
9 <test name="Util Integration Tests">
10 <classes>
11 <class name="net.postgis.tools.testutils.TestContainerController"/>
12 <class name="net.postgis.osgeo.util.UtilTest" />
13 </classes>
14 </test>
15
16 </suite>
44 <parent>
55 <artifactId>postgis-java-aggregator</artifactId>
66 <groupId>net.postgis</groupId>
7 <version>2.5.0</version>
7 <version>2021.1.0</version>
88 </parent>
99
1010 <artifactId>tools</artifactId>
11 <version>2.5.0</version>
11 <version>2021.1.0</version>
1212 <packaging>pom</packaging>
1313
1414 <name>Tools</name>
1515 <description>Miscellaneous tools and utilities</description>
1616
1717 <modules>
18 <module>osgeo-postgis-jdbc-test-util</module>
18 <module>smoketest</module>
1919 <module>test-utils</module>
2020 </modules>
2121
0 dependency-reduced-pom.xml
0 <?xml version="1.0" encoding="UTF-8"?>
1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
2 <modelVersion>4.0.0</modelVersion>
3
4 <parent>
5 <artifactId>tools</artifactId>
6 <groupId>net.postgis</groupId>
7 <version>2021.1.0</version>
8 </parent>
9
10 <artifactId>smoketest</artifactId>
11 <version>2021.1.0</version>
12 <packaging>jar</packaging>
13
14 <name>smoketest</name>
15 <description>
16 Simple smoke test util for verifying functionality postgis jdbc jar against a postgresql database with posgis
17 extensions on OSGeo-Live.
18 </description>
19
20 <properties>
21 <testTablePrefix>SMOKE_TEST</testTablePrefix>
22 </properties>
23
24 <dependencies>
25 <dependency>
26 <groupId>net.postgis</groupId>
27 <artifactId>postgis-jdbc</artifactId>
28 <version>2021.1.0</version>
29 </dependency>
30 <dependency>
31 <groupId>net.postgis</groupId>
32 <artifactId>postgis-jdbc-java2d</artifactId>
33 <version>2021.1.0</version>
34 </dependency>
35 <dependency>
36 <groupId>ch.qos.logback</groupId>
37 <artifactId>logback-classic</artifactId>
38 <version>${dependency.logback.version}</version>
39 </dependency>
40 <dependency>
41 <groupId>ch.qos.logback</groupId>
42 <artifactId>logback-core</artifactId>
43 <version>${dependency.logback.version}</version>
44 </dependency>
45 <dependency>
46 <groupId>net.postgis.tools</groupId>
47 <artifactId>test-utils</artifactId>
48 <version>2021.1.0</version>
49 <scope>test</scope>
50 </dependency>
51 </dependencies>
52
53 <build>
54 <testResources>
55 <testResource>
56 <directory>src/test/resources</directory>
57 </testResource>
58 <testResource>
59 <directory>src/test/resources-filtered</directory>
60 <filtering>true</filtering>
61 </testResource>
62 </testResources>
63 <plugins>
64 <plugin>
65 <groupId>org.apache.maven.plugins</groupId>
66 <artifactId>maven-failsafe-plugin</artifactId>
67 <executions>
68 <execution>
69 <id>integration-tests</id>
70 <goals>
71 <goal>integration-test</goal>
72 <goal>verify</goal>
73 </goals>
74 <configuration>
75 <skip>${maven.integration.test.skip}</skip>
76 <suiteXmlFiles>
77 <suiteXmlFile>${project.build.testOutputDirectory}/testng-it.xml</suiteXmlFile>
78 </suiteXmlFiles>
79 </configuration>
80 </execution>
81 </executions>
82 </plugin>
83 <plugin>
84 <groupId>org.apache.maven.plugins</groupId>
85 <artifactId>maven-shade-plugin</artifactId>
86 <executions>
87 <execution>
88 <id>shade</id>
89 <phase>package</phase>
90 <goals>
91 <goal>shade</goal>
92 </goals>
93 <configuration>
94 <artifactSet>
95 <excludes>
96 <exclude>net.postgis:postgis-jdbc</exclude>
97 </excludes>
98 </artifactSet>
99 <transformers>
100 <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
101 <mainClass>net.postgis.jdbc.smoketest.OSGeo</mainClass>
102 </transformer>
103 </transformers>
104 </configuration>
105 </execution>
106 </executions>
107 </plugin>
108 <plugin>
109 <groupId>org.apache.maven.plugins</groupId>
110 <artifactId>maven-surefire-plugin</artifactId>
111 <configuration>
112 <skip>true</skip>
113 </configuration>
114 </plugin>
115 </plugins>
116 </build>
117
118 </project>
0 /*
1 * TestAutoregister.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - example and test classes
4 *
5 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
6 *
7 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24
25 package net.postgis.jdbc.smoketest;
26
27 import net.postgis.jdbc.PGbox2d;
28 import net.postgis.jdbc.PGbox3d;
29 import net.postgis.jdbc.PGgeometry;
30 import org.postgresql.Driver;
31 import org.postgresql.util.PGobject;
32
33 import java.sql.Connection;
34 import java.sql.DriverManager;
35 import java.sql.ResultSet;
36 import java.sql.SQLException;
37 import java.sql.Statement;
38
39 /**
40 * This test program tests whether the autoregistration of PostGIS data types
41 * within the pgjdbc driver was successful. This is supposed to work with
42 * pgjdbc.jar version 8.0 and newer, and thus refuses to work with older pgjdbc
43 * versions. (But it will work fine against older servers.) It also checks for
44 * postgis version to know whether box2d is available.
45 */
46 public class Autoregister {
47
48 public static void main(String[] args) {
49 String dburl = null;
50 String dbuser = null;
51 String dbpass = null;
52
53 if (args.length == 3) {
54 System.out.println("Testing proper auto-registration");
55 dburl = args[0];
56 dbuser = args[1];
57 dbpass = args[2];
58 } else {
59 System.err.println("Usage: java examples/TestParser dburl user pass");
60 System.exit(1);
61 // Signal the compiler that code flow ends here.
62 return;
63 }
64
65 System.out.println("Driver version: " + Driver.getVersion());
66 int major;
67 try {
68 major = new Driver().getMajorVersion();
69 } catch (Exception e) {
70 System.err.println("Cannot create Driver instance: " + e.getMessage());
71 System.exit(1);
72 return;
73 }
74
75 if (major < 8) {
76 System.err.println("Your pgdjbc " + major
77 + ".X is too old, it does not support autoregistration!");
78 return;
79 }
80
81 System.out.println("Creating JDBC connection to " + dburl);
82 Connection conn = null;
83 Statement stat = null;
84 try {
85 conn = DriverManager.getConnection(dburl, dbuser, dbpass);
86 stat = conn.createStatement();
87 } catch (SQLException e) {
88 System.err.println("Connection initialization failed, aborting.");
89 e.printStackTrace();
90 System.exit(1);
91 // signal the compiler that code flow ends here:
92 throw new AssertionError();
93 }
94
95 int postgisServerMajor = 0;
96 try {
97 postgisServerMajor = getPostgisMajor(stat);
98 } catch (SQLException e) {
99 System.err.println("Error fetching PostGIS version: " + e.getMessage());
100 System.err.println("Is PostGIS really installed in the database?");
101 System.exit(1);
102 // signal the compiler that code flow ends here:
103 throw new AssertionError();
104 }
105
106 System.out.println("PostGIS Version: " + postgisServerMajor);
107
108 PGobject result = null;
109
110 /* Test geometries */
111 try {
112 ResultSet rs = stat.executeQuery("SELECT 'POINT(1 2)'::geometry");
113 rs.next();
114 result = (PGobject) rs.getObject(1);
115 if (result instanceof PGgeometry) {
116 System.out.println("PGgeometry successful!");
117 } else {
118 System.out.println("PGgeometry failed!");
119 }
120 } catch (SQLException e) {
121 System.err.println("Selecting geometry failed: " + e.getMessage());
122 System.exit(1);
123 // Signal the compiler that code flow ends here.
124 return;
125 }
126
127 /* Test box3d */
128 try {
129 ResultSet rs = stat.executeQuery("SELECT 'BOX3D(1 2 3, 4 5 6)'::box3d");
130 rs.next();
131 result = (PGobject) rs.getObject(1);
132 if (result instanceof PGbox3d) {
133 System.out.println("Box3d successful!");
134 } else {
135 System.out.println("Box3d failed!");
136 }
137 } catch (SQLException e) {
138 System.err.println("Selecting box3d failed: " + e.getMessage());
139 System.exit(1);
140 // Signal the compiler that code flow ends here.
141 return;
142 }
143
144 /* Test box2d if appropriate */
145 if (postgisServerMajor < 1) {
146 System.out.println("PostGIS version is too old, skipping box2ed test");
147 System.err.println("PostGIS version is too old, skipping box2ed test");
148 } else {
149 try {
150 ResultSet rs = stat.executeQuery("SELECT 'BOX(1 2,3 4)'::box2d");
151 rs.next();
152 result = (PGobject) rs.getObject(1);
153 if (result instanceof PGbox2d) {
154 System.out.println("Box2d successful!");
155 } else {
156 System.out.println("Box2d failed! " + result.getClass().getName());
157 }
158 } catch (SQLException e) {
159 System.err.println("Selecting box2d failed: " + e.getMessage());
160 System.exit(1);
161 // Signal the compiler that code flow ends here.
162 return;
163 }
164 }
165
166 System.out.println("Finished.");
167 // If we finished up to here without exitting, we passed all tests.
168 System.err.println("TestAutoregister.java finished without errors.");
169 }
170
171 public static int getPostgisMajor(Statement stat) throws SQLException {
172 ResultSet rs = stat.executeQuery("SELECT postgis_version()");
173 rs.next();
174 String version = rs.getString(1);
175 if (version == null) {
176 throw new SQLException("postgis_version returned NULL!");
177 }
178 version = version.trim();
179 int idx = version.indexOf('.');
180 return Integer.parseInt(version.substring(0, idx));
181 }
182 }
0 /*
1 * TestJava2d.java
2 *
3 * PostGIS extension for PostgreSQL JDBC driver - example and test classes
4 *
5 * (C) 2004 Paul Ramsey, pramsey@refractions.net
6 *
7 * (C) 2005 Markus Schaber, markus.schaber@logix-tt.com
8 *
9 * (C) 2015 Phillip Ross, phillip.w.g.ross@gmail.com
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 */
26
27 package net.postgis.jdbc.smoketest;
28
29 import java.awt.*;
30 import java.awt.event.WindowEvent;
31 import java.awt.event.WindowListener;
32 import java.awt.geom.AffineTransform;
33 import java.awt.geom.Rectangle2D;
34 import java.sql.Connection;
35 import java.sql.DriverManager;
36 import java.sql.ResultSet;
37 import java.sql.SQLException;
38 import java.util.ArrayList;
39
40 import net.postgis.jdbc.java2d.Java2DWrapper;
41
42 public class Java2d {
43 private static final boolean DEBUG = true;
44
45 public static final Shape[] SHAPEARRAY = new Shape[0];
46
47 public static final String[][] testDataset = new String[][] {
48 {"point1", "POINT(10 11)"},
49 {"multipoint1", "MULTIPOINT(10.25 11,10.5 11,10.75 11,11 11,11.25 11,11.5 11,11.75 11,12 11)"},
50 {"linestring1", "LINESTRING(0 0,100 0,100 100,0 100)"},
51 {"linestring2", "LINESTRING(-310 110,210 110,210 210,-310 210,-310 110)"},
52 {"multilinestring", "MULTILINESTRING((0 0,10 10,20 0,30 10),(40 0,40 10,50 10,50 20,60 20))"},
53 };
54
55 static {
56 new Java2DWrapper(); // make shure our driver is initialized
57 }
58
59 public static void main(String[] args) throws ClassNotFoundException, SQLException {
60
61 if (args.length != 5) {
62 System.err.println("Usage: java examples/TestJava2D dburl user pass tablename column");
63 System.err.println();
64 System.err.println("dburl has the following format:");
65 System.err.println(Java2DWrapper.POSTGIS_PROTOCOL + "//HOST:PORT/DATABASENAME");
66 System.err.println("tablename is 'jdbc_test' by default.");
67 System.exit(1);
68 }
69
70 Shape[] geometries = read(args[0], args[1], args[2], "SELECT " + args[4] + " FROM " + args[3]);
71 if (DEBUG) {
72 System.err.println("read " + geometries.length + " geometries.");
73 }
74 if (geometries.length == 0) {
75 if (DEBUG) {
76 System.err.println("No geometries were read.");
77 }
78 return;
79 }
80
81 System.err.println("Painting...");
82 Frame window = new Frame("PostGIS java2D demo");
83
84 Canvas CV = new GisCanvas(geometries);
85
86 window.add(CV);
87
88 window.setSize(500, 500);
89
90 window.addWindowListener(new EventHandler());
91
92 window.setVisible(true);
93 }
94
95 static Rectangle2D calcbbox(Shape[] geometries) {
96 Rectangle2D bbox = geometries[0].getBounds2D();
97 for (int i = 1; i < geometries.length; i++) {
98 bbox = bbox.createUnion(geometries[i].getBounds2D());
99 }
100 return bbox;
101 }
102
103 private static Shape[] read(String dburl, String dbuser, String dbpass, String query)
104 throws ClassNotFoundException, SQLException {
105 ArrayList geometries = new ArrayList();
106 if (DEBUG) {
107 System.err.println("Creating JDBC connection...");
108 }
109 Class.forName("org.postgresql.Driver");
110 Connection conn = DriverManager.getConnection(dburl, dbuser, dbpass);
111
112 if (DEBUG) {
113 System.err.println("fetching geometries: " + query);
114 }
115 ResultSet r = conn.createStatement().executeQuery(query);
116
117 while (r.next()) {
118 final Shape current = (Shape) r.getObject(1);
119 if (current != null) {
120 geometries.add(current);
121 }
122 }
123 conn.close();
124 return (Shape[]) geometries.toArray(SHAPEARRAY);
125 }
126
127 public static class GisCanvas extends Canvas {
128 /** Keep java 1.5 compiler happy */
129 private static final long serialVersionUID = 1L;
130
131 final Rectangle2D bbox;
132 final Shape[] geometries;
133
134 public GisCanvas(Shape[] geometries) {
135 this.geometries = geometries;
136 this.bbox = calcbbox(geometries);
137 setBackground(Color.GREEN);
138 }
139
140 public void paint(Graphics og) {
141 Graphics2D g = (Graphics2D) og;
142 // Add 5% padding on all borders
143 final double paddingTop = bbox.getHeight() * 0.05;
144 final double paddingBottom = bbox.getHeight() * 0.05;
145 final double paddingLeft = bbox.getWidth() * 0.05;
146 final double paddingRight = bbox.getWidth() * 0.05;
147 // If the bounding box has negative coordinates, we need to offset by the negative coordinate
148 final double offsetX = (bbox.getX() < 0) ? (0 - bbox.getX()) : 0;
149 final double offsetY = (bbox.getY() < 0) ? (0 - bbox.getY()) : 0;
150 // Scale by the bounding box and padding
151 final double scaleX = (super.getWidth() - (paddingLeft + paddingRight)) / (bbox.getWidth());
152 final double scaleY = (super.getHeight() - (paddingTop + paddingBottom)) / (bbox.getHeight());
153 // Apply the transform parameters
154 AffineTransform at = new AffineTransform();
155 at.translate(paddingLeft, paddingTop);
156 at.scale(scaleX, scaleY);
157 at.translate(offsetX, offsetY);
158
159 if (DEBUG) {
160 System.err.println();
161 System.err.println("paddingTop: " + paddingTop);
162 System.err.println("paddingBottom: " + paddingBottom);
163 System.err.println("paddingLeft: " + paddingLeft);
164 System.err.println("paddingRight: " + paddingRight);
165 System.err.println("offsetX: " + offsetX);
166 System.err.println("offsetY: " + offsetY);
167 System.err.println("scaleX: " + scaleX);
168 System.err.println("scaleY: " + scaleY);
169 System.err.println("bbox: " + bbox);
170 System.err.println("trans: " + at);
171 System.err.println("new: " + at.createTransformedShape(bbox).getBounds2D());
172 System.err.println("visual:" + super.getBounds());
173 }
174 for (int i = 0; i < geometries.length; i++) {
175 g.setPaint(Color.BLUE);
176 final Shape shape = at.createTransformedShape(geometries[i]);
177 g.fill(shape);
178 g.setPaint(Color.ORANGE);
179 g.draw(shape);
180 }
181 }
182 }
183
184 public static class EventHandler implements WindowListener {
185
186 public void windowActivated(WindowEvent e) {//
187 }
188
189 public void windowClosed(WindowEvent e) {//
190 }
191
192 public void windowClosing(WindowEvent e) {
193 e.getWindow().setVisible(false);
194 System.exit(0);
195 }
196
197 public void windowDeactivated(WindowEvent e) {//
198 }
199
200 public void windowDeiconified(WindowEvent e) {//
201 }
202
203 public void windowIconified(WindowEvent e) {//
204 }
205
206 public void windowOpened(WindowEvent e) {//
207 }
208 }
209 }
0 package net.postgis.jdbc.smoketest;
1
2 import net.postgis.jdbc.PGbox3d;
3 import net.postgis.jdbc.PGgeometry;
4 import org.slf4j.Logger;
5 import org.slf4j.LoggerFactory;
6
7 import java.sql.Connection;
8 import java.sql.DatabaseMetaData;
9 import java.sql.DriverManager;
10 import java.sql.ResultSet;
11 import java.sql.SQLException;
12 import java.sql.Statement;
13 import java.util.Objects;
14 import java.util.UUID;
15
16
17 /**
18 * Simple smoke test util for verifying functionality postgis jdbc jar against a postgresql database
19 * with posgis extensions on OSGeo-Live.
20 *
21 * @author Phillip Ross
22 */
23 public class OSGeo {
24
25 private static final Logger logger = LoggerFactory.getLogger(OSGeo.class);
26
27 private static final String DEFAULT_TEST_TABLE_PREFIX = "SMOKE_TEST";
28
29 private static final String JDBC_DRIVER_CLASS_NAME = "org.postgresql.Driver";
30
31 private Connection connection = null;
32
33 private Statement statement = null;
34
35 private String testTableName = null;
36
37
38 public OSGeo(final String jdbcUrl,
39 final String jdbcUsername,
40 final String jdbcPassword,
41 final String testTablePrefix) {
42 try {
43 Objects.requireNonNull(jdbcUrl, "A JDBC URL must be specified");
44 Objects.requireNonNull(jdbcUsername, "A database username must be specified.");
45 Objects.requireNonNull(jdbcPassword, "A database password must be specified.");
46 Objects.requireNonNull(testTablePrefix, "Unable to determine test table prefix");
47 logger.debug("Running test (url/u/p/ttp): {}/{}/{}/{}", jdbcUrl, jdbcUsername, jdbcPassword, testTablePrefix);
48 setupDatabaseResources(jdbcUrl, jdbcUsername, jdbcPassword);
49 Objects.requireNonNull(connection, "Unable to continue testing without a connection to the database");
50 if (testDatatypeRegistration()) {
51 Objects.requireNonNull(statement, "Unable to continue testing without a statement resource");
52 if (createTestTable(testTablePrefix)) {
53 if (testSQL()) {
54 logger.debug("All tests passed");
55 dropTestTable();
56 }
57 }
58 }
59 closeDatabaseResources();
60 } catch (Exception e) {
61 logger.error("Caught exception: {} {}", e.getClass().getName(), e.getMessage());
62 e.printStackTrace();
63 }
64 }
65
66
67 private boolean testSQL() {
68 final String insertPointSQL = "insert into " + testTableName + " values ('POINT (10 10 10)',1)";
69 final String insertPolygonSQL = "insert into " + testTableName + " values ('POLYGON ((0 0 0,0 10 0,10 10 0,10 0 0,0 0 0))',2)";
70
71 boolean testPass = false;
72 try {
73 logger.debug("Inserting point...");
74 statement.execute(insertPointSQL);
75
76 logger.debug("Inserting polygon...");
77 statement.execute(insertPolygonSQL);
78
79 logger.debug("Querying table...");
80 ResultSet resultSet = statement.executeQuery("select ST_AsText(geom),id from " + testTableName);
81 while (resultSet.next()) {
82 Object obj = resultSet.getObject(1);
83 int id = resultSet.getInt(2);
84 logger.debug("Row {}: {}", id, obj.toString());
85 }
86 testPass = true;
87 } catch (SQLException se) {
88 logger.error(
89 "Caught SQLException attempting to issue SQL to the database: {} {}",
90 se.getClass().getName(),
91 se.getMessage()
92 );
93 }
94 return testPass;
95 }
96
97
98 private boolean createTestTable(final String testTablePrefix) {
99 testTableName = testTablePrefix + "_" + UUID.randomUUID().toString().replaceAll("-", "");
100 final String dropSQL = "drop table " + testTableName;
101 final String createSQL = "create table " + testTableName + " (geom geometry, id int4)";
102
103 boolean testPass = false;
104 logger.debug("Creating table with geometric types...");
105 boolean tableExists = false;
106 try {
107 DatabaseMetaData databaseMetaData = connection.getMetaData();
108 try (ResultSet resultSet = databaseMetaData.getTables(null, null, testTableName.toLowerCase(), new String[] {"TABLE"})) {
109 while (resultSet.next()) {
110 tableExists = true;
111 }
112 }
113 if (tableExists) {
114 statement.execute(dropSQL);
115 }
116 statement.execute(createSQL);
117 testPass = true;
118 } catch (SQLException se) {
119 logger.error(
120 "Caught SQLException attempting to create the test table: {} {}",
121 se.getClass().getName(),
122 se.getMessage()
123 );
124 }
125 return testPass;
126 }
127
128
129 private void dropTestTable() {
130 final String dropSQL = "drop table " + testTableName;
131 logger.debug("Dropping test table");
132 boolean tableExists = false;
133 try {
134 DatabaseMetaData databaseMetaData = connection.getMetaData();
135 try (ResultSet resultSet = databaseMetaData.getTables(null, null, testTableName.toLowerCase(), new String[] {"TABLE"})) {
136 while (resultSet.next()) {
137 tableExists = true;
138 }
139 }
140 if (tableExists) {
141 statement.execute(dropSQL);
142 }
143 } catch (SQLException se) {
144 logger.error(
145 "Caught SQLException attempting to drop the test table: {} {}",
146 se.getClass().getName(),
147 se.getMessage()
148 );
149 }
150 }
151
152
153 private boolean testDatatypeRegistration() {
154 boolean testPass = false;
155 logger.debug("Adding geometric type entries...");
156 try {
157 ((org.postgresql.PGConnection)connection).addDataType("geometry", PGgeometry.class);
158 ((org.postgresql.PGConnection)connection).addDataType("box3d", PGbox3d.class);
159 testPass = true;
160 } catch (SQLException se) {
161 logger.error(
162 "Caught SQLException attempting to register datatypes with PostgreSQL driver: {} {}",
163 se.getClass().getName(),
164 se.getMessage()
165 );
166 }
167 return testPass;
168 }
169
170
171 private void closeDatabaseResources() {
172 try {
173 if (statement != null) {
174 statement.close();
175 }
176 } catch (SQLException se) {
177 logger.error(
178 "Caught SQLException attempting to close statement resource: {} {}",
179 se.getClass().getName(),
180 se.getMessage()
181 );
182 }
183 try {
184 if (connection != null) {
185 connection.close();
186 }
187 } catch (SQLException se) {
188 logger.error(
189 "Caught SQLException attempting to close connection to the database: {} {}",
190 se.getClass().getName(),
191 se.getMessage()
192 );
193 }
194 }
195
196
197 private void setupDatabaseResources(final String url, final String username, final String password) {
198 try {
199 Class.forName(JDBC_DRIVER_CLASS_NAME);
200 } catch (ClassNotFoundException e) {
201 logger.error("Caught exception attempting to load jdbc driver class {}", JDBC_DRIVER_CLASS_NAME);
202 logger.error("Check your classpath to verify that you've included the postgresql jdbc driver.");
203 }
204 try {
205 connection = DriverManager.getConnection(url, username, password);
206 statement = connection.createStatement();
207 } catch (SQLException se) {
208 logger.error(
209 "Caught SQLException attempting to setup database resources: {} {}",
210 se.getClass().getName(),
211 se.getMessage()
212 );
213 }
214 }
215
216
217 public static void main(final String[] args) {
218 if (args.length < 3) {
219 System.out.println("parameters: jdbcUrl jdbcUsername jdbcPassword [testTablePrefix]");
220 } else {
221 String jdbcUrl = args[0];
222 String jdbcUsername = args[1];
223 String jdbcPassword = args[2];
224 String testTablePrefix = DEFAULT_TEST_TABLE_PREFIX;
225 if (args.length > 3) {
226 testTablePrefix = args[3];
227 }
228 new OSGeo(jdbcUrl, jdbcUsername, jdbcPassword, testTablePrefix);
229 }
230 }
231
232
233 }
234
235 // java -classpath ~/.m2/repository/net/postgis/postgis-jdbc/2.2.1-SNAPSHOT/postgis-jdbc-2.2.1-SNAPSHOT.jar:target/smoketest-0.0.1-SNAPSHOT.jar net.postgis.osgeo.util.Main jdbc:postgresql://db01:5432/postgis1 postgis1 postgis1 smoke_test
0 #!/usr/bin/env bash
1
2 # The following sets variables based in command arguments
3 TEST_JAR="${1}" # This should be the postgis-jdbc jar file to be tested.
4 DB_HOSTNAME_AND_PORT=${2} # This should be the hostname:port of the database
5 DB_USERNAME=${3} # This should be the database user to login as.
6 DB_PASSWORD=${4} # This should be the database password to be used during login.
7
8 # The following can be changed to point to the jar containing the test utility. By default it
9 # points to a jar file in a local maven repository.
10 MVN_REPO_LOCATION=~/.m2/repository
11 GROUP_ID_DIR=/net/postgis
12 TEST_UTIL_JAR=${MVN_REPO_LOCATION}${GROUP_ID_DIR}/smoketest/0.0.1-SNAPSHOT/smoketest-0.0.1-SNAPSHOT.jar
13
14 # The following variables are derived from the variables above.
15 # They are used to invoke the JVM with the test utility.
16 JDBC_URL="jdbc:postgresql://${DB_HOSTNAME_AND_PORT}/postgis1"
17 JDBC_USERNAME=${DB_USERNAME}
18 JDBC_PASSWORD=${DB_PASSWORD}
19
20 # The exactly commandline used to invoke the utility is output before it is actually invoked.
21 echo "==> java -classpath ${TEST_JAR}:${TEST_UTIL_JAR} net.postgis.jdbc.smoketest.OSGeo ${JDBC_URL} ${JDBC_USERNAME} ${JDBC_PASSWORD}"
22
23 java -classpath ${TEST_JAR}:${TEST_UTIL_JAR} net.postgis.osgeo.util.Main ${JDBC_URL} ${JDBC_USERNAME} ${JDBC_PASSWORD}
0 package net.postgis.jdbc.smoketest;
1
2 import net.postgis.tools.testutils.TestContainerController;
3 import org.slf4j.Logger;
4 import org.slf4j.LoggerFactory;
5 import org.testng.Assert;
6 import org.testng.ITestContext;
7 import org.testng.annotations.Test;
8
9
10 /**
11 * A test class for testing the primary utility.
12 *
13 * @author Phillip Ross
14 */
15 public class UtilTest {
16
17 private static final Logger logger = LoggerFactory.getLogger(UtilTest.class);
18
19
20 @Test
21 public void test(ITestContext ctx) {
22 final String jdbcUrlSuffix = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_JDBC_URL_SUFFIX);
23 Assert.assertNotNull(jdbcUrlSuffix);
24 final String jdbcUrl = "jdbc:postgresql" + jdbcUrlSuffix;
25 final String jdbcUsername = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_USER_PARAM_NAME);
26 Assert.assertNotNull(jdbcUsername);
27 final String jdbcPassword = (String)ctx.getAttribute(TestContainerController.TEST_CONTAINER_ENV_PW_PARAM_NAME);
28 OSGeo.main(new String[] {jdbcUrl, jdbcUsername, jdbcPassword});
29 }
30
31
32 }
0 <configuration debug="false">
1
2 <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
3 <layout class="ch.qos.logback.classic.PatternLayout">
4 <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
5 </layout>
6 </appender>
7
8 <root level="debug">
9 <appender-ref ref="STDOUT" />
10 </root>
11
12 <logger name="com.github.dockerjava" level="ERROR"/>
13 <logger name="org.testcontainers" level="ERROR"/>
14 <logger name="net.postgis" level="ERROR"/>
15
16 </configuration>
0 <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
1 <suite name="OSGeo PostGIS JDBC Test Util Test Suite" verbose="1">
2
3 <parameter name="test.container.image-name" value="${test.container.image}"/>
4 <parameter name="test.container.port" value="${test.db.port}"/>
5 <parameter name="test.container.env.user" value="${test.db.username}"/>
6 <parameter name="test.container.env.password" value="${test.db.password}"/>
7 <parameter name="test.container.env.db" value="${test.db.name}"/>
8
9 <test name="Util Integration Tests">
10 <classes>
11 <class name="net.postgis.tools.testutils.TestContainerController"/>
12 <class name="net.postgis.jdbc.smoketest.UtilTest" />
13 </classes>
14 </test>
15
16 </suite>
44 <parent>
55 <groupId>net.postgis</groupId>
66 <artifactId>tools</artifactId>
7 <version>2.5.0</version>
7 <version>2021.1.0</version>
88 </parent>
99
1010 <groupId>net.postgis.tools</groupId>
1111 <artifactId>test-utils</artifactId>
12 <version>2.5.0</version>
12 <version>2021.1.0</version>
1313
1414 <name>Test Utilities</name>
1515 <description>Tools to facilities building and maintaining test suites</description>