1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 package com.sun.star.sdbcx.comp.postgresql;
23 
24 import java.util.ArrayList;
25 
26 import org.apache.openoffice.comp.sdbc.dbtools.util.Resources;
27 import org.apache.openoffice.comp.sdbc.dbtools.util.SharedResources;
28 import org.apache.openoffice.comp.sdbc.dbtools.util.StandardSQLState;
29 
30 import com.sun.star.beans.PropertyValue;
31 import com.sun.star.lang.XServiceInfo;
32 import com.sun.star.lang.XSingleComponentFactory;
33 import com.sun.star.lib.uno.helper.ComponentBase;
34 import com.sun.star.lib.uno.helper.Factory;
35 import com.sun.star.sdbc.DriverPropertyInfo;
36 import com.sun.star.sdbc.SQLException;
37 import com.sun.star.sdbc.XConnection;
38 import com.sun.star.sdbc.XDriver;
39 import com.sun.star.sdbc.XDriverManager;
40 import com.sun.star.sdbcx.XDataDefinitionSupplier;
41 import com.sun.star.sdbcx.XTablesSupplier;
42 import com.sun.star.uno.Exception;
43 import com.sun.star.uno.UnoRuntime;
44 import com.sun.star.uno.XComponentContext;
45 
46 public class PostgresqlDriver extends ComponentBase implements XServiceInfo, XDriver, XDataDefinitionSupplier {
47     private static String[] services = new String[] {
48             "com.sun.star.sdbc.Driver",
49             "com.sun.star.sdbcx.Driver"
50     };
51     private XComponentContext componentContext;
52 
__getComponentFactory(String implName)53     public static XSingleComponentFactory __getComponentFactory(String implName) {
54         XSingleComponentFactory xSingleComponentFactory = null;
55         if (implName.equals(getImplementationNameStatic())) {
56             xSingleComponentFactory = Factory.createComponentFactory(PostgresqlDriver.class,
57                     getImplementationNameStatic(), services);
58         }
59         return xSingleComponentFactory;
60     }
61 
PostgresqlDriver(XComponentContext componentContext)62     public PostgresqlDriver(XComponentContext componentContext) {
63         this.componentContext = componentContext;
64         SharedResources.registerClient(componentContext);
65     }
66 
getImplementationNameStatic()67     private static String getImplementationNameStatic() {
68         return PostgresqlDriver.class.getName();
69     }
70 
71     // XComponent:
72 
73     @Override
postDisposing()74     protected synchronized void postDisposing() {
75         componentContext = null;
76         SharedResources.revokeClient();
77     }
78 
79     // XServiceInfo:
80 
81     @Override
getImplementationName()82     public String getImplementationName() {
83         return getImplementationNameStatic();
84     }
85 
86     @Override
getSupportedServiceNames()87     public String[] getSupportedServiceNames() {
88         return services.clone();
89     }
90 
91     @Override
supportsService(String serviceName)92     public boolean supportsService(String serviceName) {
93         for (String service : getSupportedServiceNames()) {
94             if (service.equals(serviceName)) {
95                 return true;
96             }
97         }
98         return false;
99     }
100 
101     // XDriver:
102 
103     @Override
acceptsURL(String url)104     public boolean acceptsURL(String url) throws SQLException {
105         return url.startsWith("sdbc:postgresql:jdbc:");
106     }
107 
108     @Override
connect(String url, PropertyValue[] info)109     public synchronized XConnection connect(String url, PropertyValue[] info) throws SQLException {
110         checkDisposed();
111         XConnection connection = null;
112         if (acceptsURL(url)) {
113             String jdbcUrl = transformUrl(url);
114             System.out.println("Using SDBC URL " + url + " and JDBC URL " + jdbcUrl);
115 
116             try {
117                 Object driverManagerObject = componentContext.getServiceManager().createInstanceWithContext(
118                         "com.sun.star.sdbc.DriverManager", componentContext);
119                 XDriverManager driverManager = UnoRuntime.queryInterface(XDriverManager.class, driverManagerObject);
120 
121                 ArrayList<PropertyValue> properties = new ArrayList<>();
122                 boolean haveJavaClass = false;
123                 for (PropertyValue property : info) {
124                     if (property.Name.equals("JavaDriverClass")) {
125                         haveJavaClass = true;
126                     }
127                     properties.add(property);
128                 }
129                 if (!haveJavaClass) {
130                     PropertyValue javaClassProperty = new PropertyValue();
131                     javaClassProperty.Name = "JavaDriverClass";
132                     javaClassProperty.Value = "org.postgresql.Driver";
133                     properties.add(javaClassProperty);
134                 }
135                 PropertyValue[] jdbcInfo = properties.toArray(new PropertyValue[properties.size()]);
136 
137                 connection = driverManager.getConnectionWithInfo(jdbcUrl, jdbcInfo);
138                 if (connection != null) {
139                     connection = new PostgresqlConnection(connection, url);
140                 }
141             } catch (SQLException sqlException) {
142                 throw sqlException;
143             } catch (Exception exception) {
144                 throw new SQLException(exception.getMessage(), this, StandardSQLState.SQL_UNABLE_TO_CONNECT.text(), 0, exception);
145             }
146         }
147         return connection;
148     }
149 
150     @Override
getMajorVersion()151     public int getMajorVersion() {
152         return 1;
153     }
154 
155     @Override
getMinorVersion()156     public int getMinorVersion() {
157         return 0;
158     }
159 
160     @Override
getPropertyInfo(String url, PropertyValue[] info)161     public DriverPropertyInfo[] getPropertyInfo(String url, PropertyValue[] info) throws SQLException {
162         if (!acceptsURL(url)) {
163             return new DriverPropertyInfo[0];
164         }
165         return new DriverPropertyInfo [] {
166                 new DriverPropertyInfo("JavaClassName", "The JDBC driver class name.", true,
167                         "com.postgresql.Driver", new String[0]),
168         };
169     }
170 
transformUrl(String url)171     private static String transformUrl(String url) {
172         // 012345678901234567890
173         // sdbc:postgresql:jdbc:
174         return "jdbc:postgresql:" + url.substring(21);
175     }
176 
177     // XDataDefinitionSupplier:
178 
getDataDefinitionByConnection(XConnection connection)179     public synchronized XTablesSupplier getDataDefinitionByConnection(XConnection connection) throws SQLException {
180         checkDisposed();
181         return new PostgresqlCatalog((PostgresqlConnection)connection);
182     }
183 
getDataDefinitionByURL(String url, PropertyValue[] info)184     public synchronized XTablesSupplier getDataDefinitionByURL(String url, PropertyValue[] info) throws SQLException {
185         checkDisposed();
186         if (!acceptsURL(url)) {
187             String error = SharedResources.getInstance().getResourceString(Resources.STR_URI_SYNTAX_ERROR);
188             throw new SQLException(error, this, StandardSQLState.SQL_UNABLE_TO_CONNECT.text(), 0, null);
189         }
190         return getDataDefinitionByConnection(connect(url, info));
191     }
192 }
193