View Javadoc
1   /*
2    * Licensed under the Apache License, Version 2.0 (the "License");
3    * you may not use this file except in compliance with the License.
4    * You may obtain a copy of the License at
5    *
6    * http://www.apache.org/licenses/LICENSE-2.0
7    *
8    * Unless required by applicable law or agreed to in writing, software
9    * distributed under the License is distributed on an "AS IS" BASIS,
10   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11   * See the License for the specific language governing permissions and
12   * limitations under the License.
13   */
14  
15  package de.softwareforge.testing.postgres.embedded;
16  
17  import static com.google.common.base.Preconditions.checkState;
18  import static java.lang.String.format;
19  
20  import jakarta.annotation.Nonnull;
21  import java.sql.SQLException;
22  import java.util.Optional;
23  import java.util.stream.Collectors;
24  import javax.sql.DataSource;
25  
26  import com.google.auto.value.AutoValue;
27  import com.google.common.collect.ImmutableMap;
28  
29  /**
30   * Information about a database located on a PostgreSQL server connected to an {@link EmbeddedPostgres} instance.
31   */
32  @AutoValue
33  public abstract class DatabaseInfo {
34  
35      private static final String JDBC_FORMAT = "jdbc:postgresql://localhost:%d/%s?user=%s";
36  
37      DatabaseInfo() {
38      }
39  
40      /**
41       * The default user used for databases.
42       */
43      static final String PG_DEFAULT_USER = "postgres";
44  
45      /**
46       * The default database name.
47       */
48      static final String PG_DEFAULT_DB = "postgres";
49  
50      /**
51       * Returns the name of the database.
52       *
53       * @return Name of the database. Is never null.
54       */
55      @Nonnull
56      public abstract String dbName();
57  
58      /**
59       * Returns the TCP port for the database server.
60       *
61       * @return A port number. May be -1 if this objects represents an error connection.
62       */
63      public abstract int port();
64  
65      /**
66       * Returns the user that can connect to this database.
67       *
68       * @return The user name. Is never null.
69       */
70      @Nonnull
71      public abstract String user();
72  
73      /**
74       * Returns all properties that are be applied to a new data source connection to this database. See
75       * <a href="https://jdbc.postgresql.org/documentation/head/connect.html#connection-parameters">the
76       * PostgreSQL JDBC driver documentation</a> for a comprehensive list.
77       *
78       * @return Map of key-value pairs representing data source connection properties.
79       * @since 3.0
80       */
81      @Nonnull
82      public abstract ImmutableMap<String, String> connectionProperties();
83  
84      @Nonnull
85      abstract Optional<SQLException> exception();
86  
87      @Nonnull
88      static Builder builder() {
89          return new AutoValue_DatabaseInfo.Builder()
90                  .dbName(PG_DEFAULT_DB)
91                  .user(PG_DEFAULT_USER);
92      }
93  
94      @Nonnull
95      static DatabaseInfo forException(SQLException e) {
96          return builder().exception(e).port(-1).build();
97      }
98  
99      /**
100      * Returns a JDBC url to connect to the described database.
101      *
102      * @return A JDBC url that can be used to connect to the database. Never null.
103      */
104     @Nonnull
105     public String asJdbcUrl() {
106         checkState(exception().isEmpty(), "DatabaseInfo contains SQLException: %s", exception());
107 
108         String additionalParameters = connectionProperties().entrySet().stream()
109                 .map(e -> format("&%s=%s", e.getKey(), e.getValue()))
110                 .collect(Collectors.joining());
111         return format(JDBC_FORMAT, port(), dbName(), user()) + additionalParameters;
112     }
113 
114     /**
115      * Returns a {@link DataSource} instance connected to the described database.
116      *
117      * @return An initialized {@link DataSource} object. Never null.
118      * @throws SQLException A problem occurred trying to connect to the database.
119      */
120     @Nonnull
121     public DataSource asDataSource() throws SQLException {
122         if (exception().isPresent()) {
123             throw exception().get();
124         }
125 
126         return EmbeddedPostgres.createDataSource(user(), dbName(), port(), connectionProperties());
127     }
128 
129     @AutoValue.Builder
130     abstract static class Builder {
131 
132         abstract Builder dbName(String dbName);
133 
134         abstract Builder port(int port);
135 
136         abstract Builder user(String user);
137 
138         abstract Builder exception(SQLException exception);
139 
140         abstract ImmutableMap.Builder<String, String> connectionPropertiesBuilder();
141 
142         final Builder addConnectionProperty(String key, String value) {
143             connectionPropertiesBuilder().put(key, value);
144             return this;
145         }
146 
147         abstract Builder connectionProperties(ImmutableMap<String, String> connectionProperties);
148 
149         abstract DatabaseInfo build();
150 
151     }
152 }