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  package de.softwareforge.testing.postgres.embedded;
15  
16  import static com.google.common.base.Preconditions.checkState;
17  import static java.lang.String.format;
18  
19  import java.sql.SQLException;
20  import java.util.Optional;
21  import java.util.stream.Collectors;
22  import javax.sql.DataSource;
23  
24  import com.google.auto.value.AutoValue;
25  import com.google.common.collect.ImmutableMap;
26  import edu.umd.cs.findbugs.annotations.NonNull;
27  
28  /**
29   * Information about a database located on a PostgreSQL server connected to an {@link EmbeddedPostgres} instance.
30   */
31  @AutoValue
32  public abstract class DatabaseInfo {
33  
34      private static final String JDBC_FORMAT = "jdbc:postgresql://localhost:%d/%s?user=%s";
35  
36      DatabaseInfo() {
37      }
38  
39      /**
40       * The default user used for databases.
41       */
42      static final String PG_DEFAULT_USER = "postgres";
43  
44      /**
45       * The default database name.
46       */
47      static final String PG_DEFAULT_DB = "postgres";
48  
49      /**
50       * Returns the name of the database.
51       *
52       * @return Name of the database. Is never null.
53       */
54      @NonNull
55      public abstract String dbName();
56  
57      /**
58       * Returns the TCP port for the database server.
59       *
60       * @return A port number. May be -1 if this objects represents an error connection.
61       */
62      public abstract int port();
63  
64      /**
65       * Returns the user that can connect to this database.
66       *
67       * @return The user name. Is never null.
68       */
69      @NonNull
70      public abstract String user();
71  
72      /**
73       * Returns all properties that are be applied to a new data source connection to this database. See
74       * <a href="https://jdbc.postgresql.org/documentation/head/connect.html#connection-parameters">the
75       * PostgreSQL JDBC driver documentation</a> for a comprehensive list.
76       *
77       * @return Map of key-value pairs representing data source connection properties.
78       */
79      @NonNull
80      public abstract ImmutableMap<String, String> connectionProperties();
81  
82      @NonNull
83      abstract Optional<SQLException> exception();
84  
85      @NonNull
86      static Builder builder() {
87          return new AutoValue_DatabaseInfo.Builder()
88                  .dbName(PG_DEFAULT_DB)
89                  .user(PG_DEFAULT_USER);
90      }
91  
92      @NonNull
93      static DatabaseInfo forException(SQLException e) {
94          return builder().exception(e).port(-1).build();
95      }
96  
97      /**
98       * Returns a JDBC url to connect to the described database.
99       *
100      * @return A JDBC url that can be used to connect to the database. Never null.
101      */
102     @NonNull
103     public String asJdbcUrl() {
104         checkState(exception().isEmpty(), "DatabaseInfo contains SQLException: %s", exception());
105 
106         String additionalParameters = connectionProperties().entrySet().stream()
107                 .map(e -> format("&%s=%s", e.getKey(), e.getValue()))
108                 .collect(Collectors.joining());
109         return format(JDBC_FORMAT, port(), dbName(), user()) + additionalParameters;
110     }
111 
112     /**
113      * Returns a {@link DataSource} instance connected to the described database.
114      *
115      * @return An initialized {@link DataSource} object. Never null.
116      * @throws SQLException A problem occured trying to connect to the database.
117      */
118     @NonNull
119     public DataSource asDataSource() throws SQLException {
120         if (exception().isPresent()) {
121             throw exception().get();
122         }
123 
124         return EmbeddedPostgres.createDataSource(user(), dbName(), port(), connectionProperties());
125     }
126 
127     @AutoValue.Builder
128     abstract static class Builder {
129 
130         abstract Builder dbName(String dbName);
131 
132         abstract Builder port(int port);
133 
134         abstract Builder user(String user);
135 
136         abstract Builder exception(SQLException exception);
137 
138         abstract ImmutableMap.Builder<String, String> connectionPropertiesBuilder();
139 
140         final Builder addConnectionProperty(String key, String value) {
141             connectionPropertiesBuilder().put(key, value);
142             return this;
143         }
144 
145         abstract Builder connectionProperties(ImmutableMap<String, String> connectionProperties);
146 
147         abstract DatabaseInfo build();
148 
149     }
150 }