/************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2008 by Sun Microsystems, Inc. * * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: YDriver.cxx,v $ * $Revision: 1.20.30.1 $ * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_connectivity.hxx" #include "mysql/YDriver.hxx" #include "mysql/YCatalog.hxx" #include #include #include "connectivity/dbexception.hxx" #include #include #include "TConnection.hxx" #include "resource/common_res.hrc" #include "resource/sharedresources.hxx" //........................................................................ namespace connectivity { //........................................................................ using namespace mysql; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::sdbc; using namespace ::com::sun::star::sdbcx; using namespace ::com::sun::star::beans; using namespace ::com::sun::star::lang; namespace mysql { Reference< XInterface > SAL_CALL ODriverDelegator_CreateInstance(const Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxFac) throw( Exception ) { return *(new ODriverDelegator(_rxFac)); } } //==================================================================== //= ODriverDelegator //==================================================================== //-------------------------------------------------------------------- ODriverDelegator::ODriverDelegator(const Reference< XMultiServiceFactory >& _rxFactory) : ODriverDelegator_BASE(m_aMutex) ,m_xFactory(_rxFactory) ,m_bUseOdbc(sal_True) { } //-------------------------------------------------------------------- ODriverDelegator::~ODriverDelegator() { try { ::comphelper::disposeComponent(m_xODBCDriver); TJDBCDrivers::iterator aIter = m_aJdbcDrivers.begin(); TJDBCDrivers::iterator aEnd = m_aJdbcDrivers.end(); for ( ;aIter != aEnd;++aIter ) ::comphelper::disposeComponent(aIter->second); } catch(const Exception&) { } } // -------------------------------------------------------------------------------- void ODriverDelegator::disposing() { ::osl::MutexGuard aGuard(m_aMutex); for (TWeakPairVector::iterator i = m_aConnections.begin(); m_aConnections.end() != i; ++i) { Reference xTemp = i->first.get(); ::comphelper::disposeComponent(xTemp); } m_aConnections.clear(); TWeakPairVector().swap(m_aConnections); ODriverDelegator_BASE::disposing(); } namespace { sal_Bool isOdbcUrl(const ::rtl::OUString& _sUrl) { return _sUrl.copy(0,16).equalsAscii("sdbc:mysql:odbc:"); } //-------------------------------------------------------------------- ::rtl::OUString transformUrl(const ::rtl::OUString& _sUrl) { ::rtl::OUString sNewUrl = _sUrl.copy(11); if ( isOdbcUrl( _sUrl ) ) sNewUrl = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("sdbc:")) + sNewUrl; else { sNewUrl = sNewUrl.copy(5); ::rtl::OUString sTempUrl = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("jdbc:mysql://")); sTempUrl += sNewUrl; sNewUrl = sTempUrl; } return sNewUrl; } //-------------------------------------------------------------------- Reference< XDriver > lcl_loadDriver(const Reference< XMultiServiceFactory >& _rxFactory,const ::rtl::OUString& _sUrl) { Reference xDriverAccess(_rxFactory->createInstance(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sdbc.DriverManager")) ),UNO_QUERY); OSL_ENSURE(xDriverAccess.is(),"Could not load driver manager!"); Reference< XDriver > xDriver; if ( xDriverAccess.is() ) xDriver = xDriverAccess->getDriverByURL(_sUrl); return xDriver; } //-------------------------------------------------------------------- Sequence< PropertyValue > lcl_convertProperties(sal_Bool _bOdbc,const Sequence< PropertyValue >& info) { ::std::vector aProps; const PropertyValue* pSupported = info.getConstArray(); const PropertyValue* pEnd = pSupported + info.getLength(); aProps.reserve(info.getLength() + 5); for (;pSupported != pEnd; ++pSupported) { aProps.push_back( *pSupported ); } if ( _bOdbc ) { aProps.push_back( PropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Silent")) ,0 ,makeAny(sal_True) ,PropertyState_DIRECT_VALUE) ); aProps.push_back( PropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("PreventGetVersionColumns")) ,0 ,makeAny(sal_True) ,PropertyState_DIRECT_VALUE) ); } else { aProps.push_back( PropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JavaDriverClass")) ,0 ,makeAny(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.mysql.jdbc.Driver"))) ,PropertyState_DIRECT_VALUE) ); } aProps.push_back( PropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("IsAutoRetrievingEnabled")) ,0 ,makeAny(sal_True) ,PropertyState_DIRECT_VALUE) ); aProps.push_back( PropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AutoRetrievingStatement")) ,0 ,makeAny(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SELECT LAST_INSERT_ID()"))) ,PropertyState_DIRECT_VALUE) ); aProps.push_back( PropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ParameterNameSubstitution")) ,0 ,makeAny(sal_True) ,PropertyState_DIRECT_VALUE) ); PropertyValue* pProps = aProps.empty() ? 0 : &aProps[0]; return Sequence< PropertyValue >(pProps, aProps.size()); } } //-------------------------------------------------------------------- Reference< XDriver > ODriverDelegator::loadDriver( const ::rtl::OUString& url, const Sequence< PropertyValue >& info ) { Reference< XDriver > xDriver; ::rtl::OUString sCuttedUrl = transformUrl(url); sal_Bool bIsODBC = isOdbcUrl( url ); if ( bIsODBC ) { if ( !m_xODBCDriver.is() ) m_xODBCDriver = lcl_loadDriver(m_xFactory,sCuttedUrl); xDriver = m_xODBCDriver; } else { ::comphelper::NamedValueCollection aSettings( info ); ::rtl::OUString sDriverClass(RTL_CONSTASCII_USTRINGPARAM("com.mysql.jdbc.Driver")); sDriverClass = aSettings.getOrDefault( "JavaDriverClass", sDriverClass ); ::rtl::OUString sCharSet = aSettings.getOrDefault( "CharSet", ::rtl::OUString() ); TJDBCDrivers::iterator aFind = m_aJdbcDrivers.find(sDriverClass); if ( aFind == m_aJdbcDrivers.end() ) aFind = m_aJdbcDrivers.insert(TJDBCDrivers::value_type(sDriverClass,lcl_loadDriver(m_xFactory,sCuttedUrl))).first; xDriver = aFind->second; } return xDriver; } //-------------------------------------------------------------------- Reference< XConnection > SAL_CALL ODriverDelegator::connect( const ::rtl::OUString& url, const Sequence< PropertyValue >& info ) throw (SQLException, RuntimeException) { Reference< XConnection > xConnection; if ( acceptsURL(url) ) { Reference< XDriver > xDriver; xDriver = loadDriver(url,info); if ( xDriver.is() ) { ::rtl::OUString sCuttedUrl = transformUrl(url); const sal_Bool bIsODBC = isOdbcUrl( url ); Sequence< PropertyValue > aConvertedProperties = lcl_convertProperties(bIsODBC,info); if ( !bIsODBC ) { ::comphelper::NamedValueCollection aSettings( info ); ::rtl::OUString sIanaName = aSettings.getOrDefault( "CharSet", ::rtl::OUString() ); if ( sIanaName.getLength() ) { ::dbtools::OCharsetMap aLookupIanaName; ::dbtools::OCharsetMap::const_iterator aLookup = aLookupIanaName.find(sIanaName, ::dbtools::OCharsetMap::IANA()); if (aLookup != aLookupIanaName.end() ) { ::rtl::OUString sAdd; if ( RTL_TEXTENCODING_UTF8 == (*aLookup).getEncoding() ) { static const ::rtl::OUString s_sCharSetOp(RTL_CONSTASCII_USTRINGPARAM("useUnicode=true&")); if ( !sCuttedUrl.matchIgnoreAsciiCase(s_sCharSetOp) ) { sAdd = s_sCharSetOp; } // if ( !sCuttedUrl.matchIgnoreAsciiCase(s_sCharSetOp) ) } // if ( RTL_TEXTENCODING_UTF8 == (*aLookup).getEncoding() ) if ( sCuttedUrl.indexOf('?') == -1 ) sCuttedUrl += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("?")); else sCuttedUrl += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("&")); sCuttedUrl += sAdd; sCuttedUrl += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("characterEncoding=")); sCuttedUrl += sIanaName; } } } // if ( !bIsODBC ) xConnection = xDriver->connect( sCuttedUrl, aConvertedProperties ); if ( xConnection.is() ) { OMetaConnection* pMetaConnection = NULL; // now we have to set the URL to get the correct answer for metadata()->getURL() Reference< XUnoTunnel> xTunnel(xConnection,UNO_QUERY); if ( xTunnel.is() ) { pMetaConnection = reinterpret_cast(xTunnel->getSomething( OMetaConnection::getUnoTunnelImplementationId() )); if ( pMetaConnection ) pMetaConnection->setURL(url); } m_aConnections.push_back(TWeakPair(WeakReferenceHelper(xConnection),TWeakConnectionPair(WeakReferenceHelper(),pMetaConnection))); } } } return xConnection; } //-------------------------------------------------------------------- sal_Bool SAL_CALL ODriverDelegator::acceptsURL( const ::rtl::OUString& url ) throw (SQLException, RuntimeException) { sal_Bool bOK = sal_False; if ( url.getLength() >= 16 ) { ::rtl::OUString sPrefix = url.copy(0,16); bOK = sPrefix.equalsAscii("sdbc:mysql:odbc:"); if ( !bOK ) bOK = sPrefix.equalsAscii("sdbc:mysql:jdbc:"); } return bOK; } //-------------------------------------------------------------------- Sequence< DriverPropertyInfo > SAL_CALL ODriverDelegator::getPropertyInfo( const ::rtl::OUString& url, const Sequence< PropertyValue >& /*info*/ ) throw (SQLException, RuntimeException) { ::std::vector< DriverPropertyInfo > aDriverInfo; if ( !acceptsURL(url) ) return Sequence< DriverPropertyInfo >(); sal_Bool bIsODBC = isOdbcUrl( url ); Sequence< ::rtl::OUString > aBoolean(2); aBoolean[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("0")); aBoolean[1] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("1")); aDriverInfo.push_back(DriverPropertyInfo( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CharSet")) ,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CharSet of the database.")) ,sal_False ,::rtl::OUString() ,Sequence< ::rtl::OUString >()) ); aDriverInfo.push_back(DriverPropertyInfo( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SuppressVersionColumns")) ,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Display version columns (when available).")) ,sal_False ,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("0")) ,aBoolean) ); if ( !bIsODBC ) { aDriverInfo.push_back(DriverPropertyInfo( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JavaDriverClass")) ,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("The JDBC driver class name.")) ,sal_True ,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.mysql.jdbc.Driver")) ,Sequence< ::rtl::OUString >()) ); } return Sequence< DriverPropertyInfo >(&aDriverInfo[0],aDriverInfo.size()); } //-------------------------------------------------------------------- sal_Int32 SAL_CALL ODriverDelegator::getMajorVersion( ) throw (RuntimeException) { return 1; } //-------------------------------------------------------------------- sal_Int32 SAL_CALL ODriverDelegator::getMinorVersion( ) throw (RuntimeException) { return 0; } //-------------------------------------------------------------------- Reference< XTablesSupplier > SAL_CALL ODriverDelegator::getDataDefinitionByConnection( const Reference< XConnection >& connection ) throw (SQLException, RuntimeException) { ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(ODriverDelegator_BASE::rBHelper.bDisposed); Reference< XTablesSupplier > xTab; Reference< XUnoTunnel> xTunnel(connection,UNO_QUERY); if ( xTunnel.is() ) { OMetaConnection* pConnection = reinterpret_cast(xTunnel->getSomething( OMetaConnection::getUnoTunnelImplementationId() )); if ( pConnection ) { TWeakPairVector::iterator aEnd = m_aConnections.end(); for (TWeakPairVector::iterator i = m_aConnections.begin(); aEnd != i; ++i) { if ( i->second.second == pConnection ) { xTab = Reference< XTablesSupplier >(i->second.first.get().get(),UNO_QUERY); if ( !xTab.is() ) { xTab = new OMySQLCatalog(connection); i->second.first = WeakReferenceHelper(xTab); } break; } } } } return xTab; } //-------------------------------------------------------------------- Reference< XTablesSupplier > SAL_CALL ODriverDelegator::getDataDefinitionByURL( const ::rtl::OUString& url, const Sequence< PropertyValue >& info ) throw (SQLException, RuntimeException) { if ( ! acceptsURL(url) ) { ::connectivity::SharedResources aResources; const ::rtl::OUString sMessage = aResources.getResourceString(STR_URI_SYNTAX_ERROR); ::dbtools::throwGenericSQLException(sMessage ,*this); } // if ( ! acceptsURL(url) ) return getDataDefinitionByConnection(connect(url,info)); } // XServiceInfo // -------------------------------------------------------------------------------- //------------------------------------------------------------------------------ rtl::OUString ODriverDelegator::getImplementationName_Static( ) throw(RuntimeException) { return rtl::OUString::createFromAscii("org.openoffice.comp.drivers.MySQL.Driver"); } //------------------------------------------------------------------------------ Sequence< ::rtl::OUString > ODriverDelegator::getSupportedServiceNames_Static( ) throw (RuntimeException) { Sequence< ::rtl::OUString > aSNS( 2 ); aSNS[0] = ::rtl::OUString::createFromAscii("com.sun.star.sdbc.Driver"); aSNS[1] = ::rtl::OUString::createFromAscii("com.sun.star.sdbcx.Driver"); return aSNS; } //------------------------------------------------------------------ ::rtl::OUString SAL_CALL ODriverDelegator::getImplementationName( ) throw(RuntimeException) { return getImplementationName_Static(); } //------------------------------------------------------------------ sal_Bool SAL_CALL ODriverDelegator::supportsService( const ::rtl::OUString& _rServiceName ) throw(RuntimeException) { Sequence< ::rtl::OUString > aSupported(getSupportedServiceNames()); const ::rtl::OUString* pSupported = aSupported.getConstArray(); const ::rtl::OUString* pEnd = pSupported + aSupported.getLength(); for (;pSupported != pEnd && !pSupported->equals(_rServiceName); ++pSupported) ; return pSupported != pEnd; } //------------------------------------------------------------------ Sequence< ::rtl::OUString > SAL_CALL ODriverDelegator::getSupportedServiceNames( ) throw(RuntimeException) { return getSupportedServiceNames_Static(); } //------------------------------------------------------------------ //........................................................................ } // namespace connectivity //........................................................................