1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org 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
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_connectivity.hxx"
30 #include <cppuhelper/typeprovider.hxx>
31 #include "adabas/BConnection.hxx"
32 #include "adabas/BDriver.hxx"
33 #include "adabas/BCatalog.hxx"
34 #include "odbc/OFunctions.hxx"
35 #include "odbc/OTools.hxx"
36 #ifndef _CONNECTIVITY_ODBC_ODATABASEMETADATA_HXX_
37 #include "adabas/BDatabaseMetaData.hxx"
38 #endif
39 #include "adabas/BStatement.hxx"
40 #include "adabas/BPreparedStatement.hxx"
41 #include <com/sun/star/lang/DisposedException.hpp>
42 #include <connectivity/dbcharset.hxx>
43 #include "connectivity/sqliterator.hxx"
44 #include <connectivity/sqlparse.hxx>
45 
46 #include <string.h>
47 
48 using namespace connectivity::adabas;
49 using namespace connectivity;
50 using namespace ::com::sun::star::uno;
51 using namespace ::com::sun::star::beans;
52 using namespace ::com::sun::star::sdbcx;
53 using namespace ::com::sun::star::sdbc;
54 using namespace ::com::sun::star::container;
55 using namespace ::com::sun::star::lang;
56 
57 
58 //------------------------------------------------------------------------------
59 namespace starlang	= ::com::sun::star::lang;
60 // --------------------------------------------------------------------------------
61 OAdabasConnection::OAdabasConnection(const SQLHANDLE _pDriverHandle, connectivity::odbc::ODBCDriver*        _pDriver)
62                                                  : OConnection_BASE2(_pDriverHandle,_pDriver)
63 {
64 	m_bUseOldDateFormat = sal_True;
65 }
66 //-----------------------------------------------------------------------------
67 SQLRETURN OAdabasConnection::Construct( const ::rtl::OUString& url,const Sequence< PropertyValue >& info) throw(SQLException)
68 {
69 	::osl::MutexGuard aGuard( m_aMutex );
70 
71 	m_aConnectionHandle  = SQL_NULL_HANDLE;
72 	setURL(url);
73 	setConnectionInfo(info);
74 
75 	// Connection allozieren
76 	N3SQLAllocHandle(SQL_HANDLE_DBC,m_pDriverHandleCopy,&m_aConnectionHandle);
77 	if(m_aConnectionHandle == SQL_NULL_HANDLE)
78 		throw SQLException();
79 
80 	const PropertyValue *pBegin	= info.getConstArray();
81 	const PropertyValue *pEnd	= pBegin + info.getLength();
82 	::rtl::OUString sHostName;
83 
84 	sal_Int32 nLen = url.indexOf(':');
85 	nLen = url.indexOf(':',nLen+1);
86 	::rtl::OUString aDSN(url.copy(nLen+1)),aUID,aPWD;
87 	sal_Int32 nTimeout = 20;
88 	for(;pBegin != pEnd;++pBegin)
89 	{
90 		if ( !pBegin->Name.compareToAscii("Timeout") )
91 			pBegin->Value >>= nTimeout;
92 		else if(!pBegin->Name.compareToAscii("user"))
93 			pBegin->Value >>= aUID;
94 		else if(!pBegin->Name.compareToAscii("password"))
95 			pBegin->Value >>= aPWD;
96 		else if(!pBegin->Name.compareToAscii("HostName"))
97 			pBegin->Value >>= sHostName;
98 		else if(0 == pBegin->Name.compareToAscii("CharSet"))
99 		{
100 			::rtl::OUString sIanaName;
101 			OSL_VERIFY( pBegin->Value >>= sIanaName );
102 
103 			::dbtools::OCharsetMap aLookupIanaName;
104 			::dbtools::OCharsetMap::const_iterator aLookup = aLookupIanaName.find(sIanaName, ::dbtools::OCharsetMap::IANA());
105 			if (aLookup != aLookupIanaName.end())
106 				m_nTextEncoding = (*aLookup).getEncoding();
107 			else
108 				m_nTextEncoding = RTL_TEXTENCODING_DONTKNOW;
109 			if(m_nTextEncoding == RTL_TEXTENCODING_DONTKNOW)
110 				m_nTextEncoding = osl_getThreadTextEncoding();
111 		}
112 	}
113 	m_sUser = aUID;
114 
115 	if ( sHostName.getLength() )
116 		aDSN = sHostName + ':' + aDSN;
117 	SQLRETURN nSQLRETURN = openConnectionWithAuth(aDSN,nTimeout, aUID,aPWD);
118 
119 	return nSQLRETURN;
120 }
121 //-----------------------------------------------------------------------------
122 SQLRETURN OAdabasConnection::openConnectionWithAuth(const ::rtl::OUString& aConnectStr,sal_Int32 nTimeOut, const ::rtl::OUString& _uid,const ::rtl::OUString& _pwd)
123 {
124 	if (m_aConnectionHandle == SQL_NULL_HANDLE)
125 		return -1;
126 
127 	SQLRETURN nSQLRETURN = 0;
128 	SDB_ODBC_CHAR szDSN[4096];
129 	SDB_ODBC_CHAR szUID[20];
130 	SDB_ODBC_CHAR szPWD[20];
131 
132 	memset(szDSN,'\0',4096);
133 	memset(szUID,'\0',20);
134 	memset(szPWD,'\0',20);
135 
136 	::rtl::OString aConStr(::rtl::OUStringToOString(aConnectStr,getTextEncoding()));
137 	::rtl::OString aUID(::rtl::OUStringToOString(_uid,getTextEncoding()));
138 	::rtl::OString aPWD(::rtl::OUStringToOString(_pwd,getTextEncoding()));
139 	memcpy(szDSN, (SDB_ODBC_CHAR*) aConStr.getStr(), ::std::min<sal_Int32>((sal_Int32)2048,aConStr.getLength()));
140 	memcpy(szUID, (SDB_ODBC_CHAR*) aUID.getStr(), ::std::min<sal_Int32>((sal_Int32)20,aUID.getLength()));
141 	memcpy(szPWD, (SDB_ODBC_CHAR*) aPWD.getStr(), ::std::min<sal_Int32>((sal_Int32)20,aPWD.getLength()));
142 
143 
144 
145 	N3SQLSetConnectAttr(m_aConnectionHandle,SQL_ATTR_LOGIN_TIMEOUT,(SQLPOINTER)nTimeOut,SQL_IS_INTEGER);
146 	// Verbindung aufbauen
147 
148 	nSQLRETURN = N3SQLConnect(m_aConnectionHandle,
149 					  szDSN,
150 					  (SQLSMALLINT) ::std::min<sal_Int32>((sal_Int32)2048,aConStr.getLength()),
151 					  szUID,
152 					  (SQLSMALLINT) ::std::min<sal_Int32>((sal_Int32)20,aUID.getLength()),
153 					  szPWD,
154 					  (SQLSMALLINT) ::std::min<sal_Int32>((sal_Int32)20,aPWD.getLength()));
155 	if (nSQLRETURN == SQL_ERROR || nSQLRETURN == SQL_NO_DATA)
156 		return nSQLRETURN;
157 
158 	m_bClosed = sal_False;
159 
160 	// autocoomit ist immer default
161 
162 	N3SQLSetConnectAttr(m_aConnectionHandle,SQL_ATTR_AUTOCOMMIT,(SQLPOINTER)SQL_AUTOCOMMIT_ON,SQL_IS_INTEGER);
163 
164 	return nSQLRETURN;
165 }
166 
167 //------------------------------------------------------------------------------
168 void OAdabasConnection::disposing()
169 {
170 	::osl::MutexGuard aGuard(m_aMutex);
171 
172 	Reference< XTablesSupplier > xTableSupplier(m_xCatalog);
173     ::comphelper::disposeComponent(xTableSupplier);
174 
175 	m_xCatalog = WeakReference< XTablesSupplier >();
176 
177     OConnection_BASE2::disposing();
178 }
179 //------------------------------------------------------------------------------
180 Reference< XTablesSupplier > OAdabasConnection::createCatalog()
181 {
182 	::osl::MutexGuard aGuard( m_aMutex );
183 	Reference< XTablesSupplier > xTab = m_xCatalog;
184 	if(!xTab.is())
185 	{
186 		xTab = new OAdabasCatalog(m_aConnectionHandle,this);
187 		m_xCatalog = xTab;
188 	}
189 	return xTab;
190 }
191 // --------------------------------------------------------------------------------
192 Reference< XDatabaseMetaData > SAL_CALL OAdabasConnection::getMetaData(  ) throw(SQLException, RuntimeException)
193 {
194 	::osl::MutexGuard aGuard( m_aMutex );
195 	checkDisposed(OConnection_BASE2::rBHelper.bDisposed);
196 
197 
198 	Reference< XDatabaseMetaData > xMetaData = m_xMetaData;
199 	if(!xMetaData.is())
200 	{
201 		xMetaData = new OAdabasDatabaseMetaData(m_aConnectionHandle,this);
202 		m_xMetaData = xMetaData;
203 	}
204 
205 	return xMetaData;
206 }
207 // --------------------------------------------------------------------------------
208 Reference< XStatement > SAL_CALL OAdabasConnection::createStatement(  ) throw(SQLException, RuntimeException)
209 {
210 	::osl::MutexGuard aGuard( m_aMutex );
211 	checkDisposed(OConnection_BASE2::rBHelper.bDisposed);
212 
213 	Reference< XStatement > xReturn = new OAdabasStatement(this);
214 	m_aStatements.push_back(WeakReferenceHelper(xReturn));
215 	return xReturn;
216 }
217 // --------------------------------------------------------------------------------
218 Reference< XPreparedStatement > SAL_CALL OAdabasConnection::prepareStatement( const ::rtl::OUString& sql ) throw(SQLException, RuntimeException)
219 {
220 	::osl::MutexGuard aGuard( m_aMutex );
221 	checkDisposed(OConnection_BASE2::rBHelper.bDisposed);
222 
223 	Reference< XPreparedStatement > xReturn = new OAdabasPreparedStatement(this,sql);
224 	m_aStatements.push_back(WeakReferenceHelper(xReturn));
225 	return xReturn;
226 }
227 // -----------------------------------------------------------------------------
228 sal_Int64 SAL_CALL OAdabasConnection::getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& rId ) throw (::com::sun::star::uno::RuntimeException)
229 {
230 	return (rId.getLength() == 16 && 0 == rtl_compareMemory(getUnoTunnelImplementationId().getConstArray(),  rId.getConstArray(), 16 ) )
231 				? reinterpret_cast< sal_Int64 >( this )
232 				: OConnection_BASE2::getSomething(rId);
233 }
234 // -----------------------------------------------------------------------------
235 Sequence< sal_Int8 > OAdabasConnection::getUnoTunnelImplementationId()
236 {
237 	static ::cppu::OImplementationId * pId = 0;
238 	if (! pId)
239 	{
240 		::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
241 		if (! pId)
242 		{
243 			static ::cppu::OImplementationId aId;
244 			pId = &aId;
245 		}
246 	}
247 	return pId->getImplementationId();
248 }
249 // -----------------------------------------------------------------------------
250 ::connectivity::odbc::OConnection* OAdabasConnection::cloneConnection()
251 {
252 	return new OAdabasConnection(m_pDriverHandleCopy,m_pDriver);
253 }
254 // -----------------------------------------------------------------------------
255 ::vos::ORef<OSQLColumns> OAdabasConnection::createSelectColumns(const ::rtl::OUString& _rSql)
256 {
257 	::vos::ORef<OSQLColumns> aRet;
258 	OSQLParser aParser(getDriver()->getORB());
259 	::rtl::OUString sErrorMessage;
260 	OSQLParseNode* pNode = aParser.parseTree(sErrorMessage,_rSql);
261 	if(pNode)
262 	{
263 		Reference< XTablesSupplier> xCata = createCatalog();
264 		OSQLParseTreeIterator aParseIter(this, xCata->getTables(),
265 										aParser, pNode);
266 		aParseIter.traverseAll();
267 		aRet = aParseIter.getSelectColumns();
268 	}
269 	return aRet;
270 }
271 // -----------------------------------------------------------------------------
272 
273 
274 
275