1 /*
2  * This file is part of the LibreOffice project.
3  *
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7  *
8  * This file incorporates work covered by the following license notice:
9  *
10  *   Licensed to the Apache Software Foundation (ASF) under one or more
11  *   contributor license agreements. See the NOTICE file distributed
12  *   with this work for additional information regarding copyright
13  *   ownership. The ASF licenses this file to you under the Apache
14  *   License, Version 2.0 (the "License"); you may not use this file
15  *   except in compliance with the License. You may obtain a copy of
16  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
17  */
18 package connectivity.tools;
19 
20 import com.sun.star.container.XNameAccess;
21 import com.sun.star.frame.XModel;
22 import com.sun.star.frame.XStorable;
23 import com.sun.star.io.IOException;
24 import com.sun.star.lang.XMultiServiceFactory;
25 import com.sun.star.sdb.XDocumentDataSource;
26 import com.sun.star.sdb.XOfficeDatabaseDocument;
27 import com.sun.star.sdbc.SQLException;
28 import com.sun.star.sdbc.XCloseable;
29 import com.sun.star.sdbc.XStatement;
30 import com.sun.star.uno.UnoRuntime;
31 import com.sun.star.util.CloseVetoException;
32 import connectivity.tools.sdb.Connection;
33 import java.io.File;
34 import static org.junit.Assert.*;
35 
36 public abstract class AbstractDatabase implements DatabaseAccess
37 {
AbstractDatabase(final XMultiServiceFactory orb)38     public AbstractDatabase(final XMultiServiceFactory orb) throws Exception
39     {
40         m_orb = orb;
41     }
42 
43 
AbstractDatabase(final XMultiServiceFactory orb, final String _existingDocumentURL )44     public AbstractDatabase(final XMultiServiceFactory orb, final String _existingDocumentURL ) throws Exception
45     {
46         m_orb = orb;
47         createDBDocument( _existingDocumentURL );
48     }
49 
50     /** returns a connection to the database
51      *
52      * Multiple calls to this method return the same connection. The DbaseDatabase object keeps
53      * the ownership of the connection, so you don't need to (and should not) dispose/close it.
54      */
defaultConnection()55     public Connection defaultConnection() throws SQLException
56     {
57         if ( m_connection == null )
58             m_connection = new Connection( m_databaseDocument.getDataSource().getConnection("", "") );
59 
60         return m_connection;
61     }
62 
63     /** executes the given SQL statement via the defaultConnection
64      */
executeSQL(final String statementString)65     public void executeSQL(final String statementString) throws SQLException
66     {
67         final XStatement statement = defaultConnection().createStatement();
68         statement.execute(statementString);
69     }
70 
71     /** stores the database document
72      */
store()73     public void store() throws IOException
74     {
75         if (m_databaseDocument != null)
76         {
77             final XStorable storeDoc = UnoRuntime.queryInterface(XStorable.class, m_databaseDocument);
78             storeDoc.store();
79         }
80     }
81 
82     /** closes the database document
83      *
84      *  Any CloseVetoExceptions fired by third parties are ignored, and any reference to the
85      *  database document is released.
86      */
close()87     public void close()
88     {
89         // close connection
90         final XCloseable closeConn = UnoRuntime.queryInterface( XCloseable.class,
91             m_connection != null ? m_connection.getXConnection() : null );
92         if (closeConn != null)
93         {
94             try
95             {
96                 closeConn.close();
97             }
98             catch (SQLException e)
99             {
100             }
101         }
102         m_connection = null;
103 
104         // close document
105         final com.sun.star.util.XCloseable closeDoc = UnoRuntime.queryInterface( com.sun.star.util.XCloseable.class, m_databaseDocument );
106         if (closeDoc != null)
107         {
108             try
109             {
110                 closeDoc.close(true);
111             }
112             catch (CloseVetoException e)
113             {
114             }
115         }
116         m_databaseDocument = null;
117     }
118 
119     /** closes the document, and deletes the underlying file
120      */
closeAndDelete()121     public void closeAndDelete()
122     {
123         close();
124         delete();
125     }
126 
delete()127     protected void delete() {}
128 
129     /** returns the underlying database document
130      */
getDatabaseDocument()131     public XOfficeDatabaseDocument getDatabaseDocument()
132     {
133         return m_databaseDocument;
134     }
135 
136     /** returns the model interface of the underlying database document
137      */
getModel()138     public XModel getModel()
139     {
140         return UnoRuntime.queryInterface( XModel.class, m_databaseDocument );
141     }
142 
getORB()143     public XMultiServiceFactory getORB()
144     {
145         return m_orb;
146     }
147 
148 
createDBDocument(final String _docURL)149     final private void createDBDocument(final String _docURL) throws Exception
150     {
151         m_databaseDocumentFile = _docURL;
152 
153         final XNameAccess dbContext = UnoRuntime.queryInterface( XNameAccess.class,
154             m_orb.createInstance( "com.sun.star.sdb.DatabaseContext" ) );
155         final XDocumentDataSource dataSource = UnoRuntime.queryInterface( XDocumentDataSource.class, dbContext.getByName( _docURL ) );
156 
157         m_databaseDocument = dataSource.getDatabaseDocument();
158         m_dataSource = new DataSource(m_databaseDocument.getDataSource());
159     }
160 
161     /** returns the URL of the ODB document represented by this instance
162      */
getDocumentURL()163     public String getDocumentURL()
164     {
165         return m_databaseDocumentFile;
166     }
167 
168     /** returns the data source belonging to this database
169      */
getDataSource()170     public DataSource getDataSource()
171     {
172         return m_dataSource;
173     }
174 
175     /** creates a row set operating the database, with a given command/type
176      */
createRowSet(final int _commandType, final String _command)177     public RowSet createRowSet(final int _commandType, final String _command)
178     {
179         return new RowSet(m_orb, getDocumentURL(), _commandType, _command);
180     }
181 
182     @Override
finalize()183     protected void finalize() throws Throwable
184     {
185         // Cannot call close() here, as it accesses UNO objects (that may
186         // already have been finalized):
187         assertNull(
188             "missing call to connectivity.tools.AbstractDatabase.close",
189             m_connection);
190         assertNull(
191             "missing call to connectivity.tools.AbstractDatabase.close",
192             m_databaseDocument);
193 
194         delete();
195         super.finalize();
196     }
197 
198     // the service factory
199     protected final XMultiServiceFactory m_orb;
200     // the URL of the temporary file used for the database document
201     protected String m_databaseDocumentFile;
202     // the database document
203     protected XOfficeDatabaseDocument m_databaseDocument;
204     // the data source belonging to the database document
205     protected DataSource m_dataSource;
206     // the default connection
207     private Connection    m_connection;
208 }
209