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 "hsqldb/HStorageMap.hxx" 31 #include <comphelper/types.hxx> 32 #include <com/sun/star/embed/XTransactionBroadcaster.hpp> 33 #include <com/sun/star/embed/XTransactedObject.hpp> 34 #include <com/sun/star/embed/ElementModes.hpp> 35 #include <com/sun/star/lang/DisposedException.hpp> 36 #include "diagnose_ex.h" 37 #include <osl/thread.h> 38 39 //........................................................................ 40 namespace connectivity 41 { 42 //........................................................................ 43 namespace hsqldb 44 { 45 //........................................................................ 46 using namespace ::com::sun::star::uno; 47 using namespace ::com::sun::star::lang; 48 using namespace ::com::sun::star::embed; 49 using namespace ::com::sun::star::io; 50 51 #define ThrowException(env, type, msg) { \ 52 env->ThrowNew(env->FindClass(type), msg); } 53 54 55 StreamHelper::StreamHelper(const Reference< XStream>& _xStream) 56 : m_xStream(_xStream) 57 { 58 } 59 // ----------------------------------------------------------------------------- 60 StreamHelper::~StreamHelper() 61 { 62 try 63 { 64 m_xStream.clear(); 65 m_xSeek.clear(); 66 if ( m_xInputStream.is() ) 67 { 68 m_xInputStream->closeInput(); 69 m_xInputStream.clear(); 70 } 71 // this is done implicity by the closing of the input stream 72 else if ( m_xOutputStream.is() ) 73 { 74 m_xOutputStream->closeOutput(); 75 try 76 { 77 ::comphelper::disposeComponent(m_xOutputStream); 78 } 79 catch(DisposedException&) 80 { 81 } 82 catch(const Exception& e) 83 { 84 OSL_UNUSED( e ); 85 OSL_ENSURE(0,"Could not dispose OutputStream"); 86 } 87 m_xOutputStream.clear(); 88 } 89 } 90 catch(Exception& ex) 91 { 92 OSL_UNUSED( ex ); 93 OSL_ENSURE(0,"Exception catched!"); 94 } 95 } 96 // ----------------------------------------------------------------------------- 97 Reference< XInputStream> StreamHelper::getInputStream() 98 { 99 if ( !m_xInputStream.is() ) 100 m_xInputStream = m_xStream->getInputStream(); 101 return m_xInputStream; 102 } 103 // ----------------------------------------------------------------------------- 104 Reference< XOutputStream> StreamHelper::getOutputStream() 105 { 106 if ( !m_xOutputStream.is() ) 107 m_xOutputStream = m_xStream->getOutputStream(); 108 return m_xOutputStream; 109 } 110 // ----------------------------------------------------------------------------- 111 Reference< XSeekable> StreamHelper::getSeek() 112 { 113 if ( !m_xSeek.is() ) 114 m_xSeek.set(m_xStream,UNO_QUERY); 115 return m_xSeek; 116 } 117 // ----------------------------------------------------------------------------- 118 TStorages& lcl_getStorageMap() 119 { 120 static TStorages s_aMap; 121 return s_aMap; 122 } 123 // ----------------------------------------------------------------------------- 124 ::rtl::OUString lcl_getNextCount() 125 { 126 static sal_Int32 s_nCount = 0; 127 return ::rtl::OUString::valueOf(s_nCount++); 128 } 129 // ----------------------------------------------------------------------------- 130 ::rtl::OUString StorageContainer::removeURLPrefix(const ::rtl::OUString& _sURL,const ::rtl::OUString& _sFileURL) 131 { 132 return _sURL.copy(_sFileURL.getLength()+1); 133 } 134 // ----------------------------------------------------------------------------- 135 ::rtl::OUString StorageContainer::removeOldURLPrefix(const ::rtl::OUString& _sURL) 136 { 137 ::rtl::OUString sRet = _sURL; 138 #if defined(WNT) 139 sal_Int32 nIndex = sRet.lastIndexOf('\\'); 140 #else 141 sal_Int32 nIndex = sRet.lastIndexOf('/'); 142 #endif 143 if ( nIndex != -1 ) 144 { 145 sRet = _sURL.copy(nIndex+1); 146 } 147 return sRet; 148 149 } 150 /*****************************************************************************/ 151 /* convert jstring to rtl_uString */ 152 153 ::rtl::OUString StorageContainer::jstring2ustring(JNIEnv * env, jstring jstr) 154 { 155 if (JNI_FALSE != env->ExceptionCheck()) 156 { 157 env->ExceptionClear(); 158 OSL_ENSURE(0,"ExceptionClear"); 159 } 160 ::rtl::OUString aStr; 161 if ( jstr ) 162 { 163 jboolean bCopy(sal_True); 164 const jchar* pChar = env->GetStringChars(jstr,&bCopy); 165 jsize len = env->GetStringLength(jstr); 166 aStr = ::rtl::OUString(pChar,len); 167 168 if(bCopy) 169 env->ReleaseStringChars(jstr,pChar); 170 } 171 172 if (JNI_FALSE != env->ExceptionCheck()) 173 { 174 env->ExceptionClear(); 175 OSL_ENSURE(0,"ExceptionClear"); 176 } 177 return aStr; 178 } 179 180 // ----------------------------------------------------------------------------- 181 ::rtl::OUString StorageContainer::registerStorage(const Reference< XStorage>& _xStorage,const ::rtl::OUString& _sURL) 182 { 183 OSL_ENSURE(_xStorage.is(),"Storage is NULL!"); 184 TStorages& rMap = lcl_getStorageMap(); 185 // check if the storage is already in our map 186 TStorages::iterator aFind = ::std::find_if(rMap.begin(),rMap.end(), 187 ::std::compose1( 188 ::std::bind2nd(::std::equal_to<Reference<XStorage> >(),_xStorage) 189 ,::std::compose1(::std::select1st<TStorageURLPair>(),::std::compose1(::std::select1st<TStorages::mapped_type>(),::std::select2nd<TStorages::value_type>()))) 190 ); 191 if ( aFind == rMap.end() ) 192 { 193 aFind = rMap.insert(TStorages::value_type(lcl_getNextCount(),TStorages::mapped_type(TStorageURLPair(_xStorage,_sURL),TStreamMap()))).first; 194 } 195 196 return aFind->first; 197 } 198 // ----------------------------------------------------------------------------- 199 TStorages::mapped_type StorageContainer::getRegisteredStorage(const ::rtl::OUString& _sKey) 200 { 201 TStorages::mapped_type aRet; 202 TStorages& rMap = lcl_getStorageMap(); 203 TStorages::iterator aFind = rMap.find(_sKey); 204 OSL_ENSURE(aFind != rMap.end(),"Storage could not be found in list!"); 205 if ( aFind != rMap.end() ) 206 aRet = aFind->second; 207 208 return aRet; 209 } 210 // ----------------------------------------------------------------------------- 211 ::rtl::OUString StorageContainer::getRegisteredKey(const Reference< XStorage>& _xStorage) 212 { 213 ::rtl::OUString sKey; 214 OSL_ENSURE(_xStorage.is(),"Storage is NULL!"); 215 TStorages& rMap = lcl_getStorageMap(); 216 // check if the storage is already in our map 217 TStorages::iterator aFind = ::std::find_if(rMap.begin(),rMap.end(), 218 ::std::compose1( 219 ::std::bind2nd(::std::equal_to<Reference<XStorage> >(),_xStorage) 220 ,::std::compose1(::std::select1st<TStorageURLPair>(),::std::compose1(::std::select1st<TStorages::mapped_type>(),::std::select2nd<TStorages::value_type>()))) 221 ); 222 if ( aFind != rMap.end() ) 223 sKey = aFind->first; 224 return sKey; 225 } 226 // ----------------------------------------------------------------------------- 227 void StorageContainer::revokeStorage(const ::rtl::OUString& _sKey,const Reference<XTransactionListener>& _xListener) 228 { 229 TStorages& rMap = lcl_getStorageMap(); 230 TStorages::iterator aFind = rMap.find(_sKey); 231 if ( aFind != rMap.end() ) 232 { 233 try 234 { 235 if ( _xListener.is() ) 236 { 237 Reference<XTransactionBroadcaster> xBroad(aFind->second.first.first,UNO_QUERY); 238 if ( xBroad.is() ) 239 xBroad->removeTransactionListener(_xListener); 240 Reference<XTransactedObject> xTrans(aFind->second.first.first,UNO_QUERY); 241 if ( xTrans.is() ) 242 xTrans->commit(); 243 } 244 } 245 catch(Exception&) 246 { 247 } 248 rMap.erase(aFind); 249 } 250 } 251 // ----------------------------------------------------------------------------- 252 TStreamMap::mapped_type StorageContainer::registerStream(JNIEnv * env,jstring name, jstring key,sal_Int32 _nMode) 253 { 254 TStreamMap::mapped_type pHelper; 255 TStorages& rMap = lcl_getStorageMap(); 256 ::rtl::OUString sKey = jstring2ustring(env,key); 257 TStorages::iterator aFind = rMap.find(sKey); 258 OSL_ENSURE(aFind != rMap.end(),"Storage could not be found in list!"); 259 if ( aFind != rMap.end() ) 260 { 261 TStorages::mapped_type aStoragePair = StorageContainer::getRegisteredStorage(sKey); 262 OSL_ENSURE(aStoragePair.first.first.is(),"No Storage available!"); 263 if ( aStoragePair.first.first.is() ) 264 { 265 ::rtl::OUString sOrgName = StorageContainer::jstring2ustring(env,name); 266 ::rtl::OUString sName = removeURLPrefix(sOrgName,aStoragePair.first.second); 267 TStreamMap::iterator aStreamFind = aFind->second.second.find(sName); 268 OSL_ENSURE( aStreamFind == aFind->second.second.end(),"A Stream was already registered for this object!"); 269 if ( aStreamFind != aFind->second.second.end() ) 270 { 271 pHelper = aStreamFind->second; 272 } 273 else 274 { 275 try 276 { 277 try 278 { 279 pHelper.reset(new StreamHelper(aStoragePair.first.first->openStreamElement(sName,_nMode))); 280 } 281 catch(Exception& ) 282 { 283 ::rtl::OUString sStrippedName = removeOldURLPrefix(sOrgName); 284 285 if ( ((_nMode & ElementModes::WRITE) != ElementModes::WRITE ) ) 286 { 287 sal_Bool bIsStream = sal_True; 288 try 289 { 290 bIsStream = aStoragePair.first.first->isStreamElement(sStrippedName); 291 } 292 catch(Exception& ) 293 { 294 bIsStream = sal_False; 295 } 296 if ( !bIsStream ) 297 return pHelper; // readonly file without data stream 298 } 299 pHelper.reset( new StreamHelper(aStoragePair.first.first->openStreamElement( sStrippedName, _nMode ) ) ); 300 } 301 aFind->second.second.insert(TStreamMap::value_type(sName,pHelper)); 302 } 303 catch(Exception& e) 304 { 305 #if OSL_DEBUG_LEVEL > 0 306 ::rtl::OString sMessage( "[HSQLDB-SDBC] caught an exception while opening a stream\n" ); 307 sMessage += "Name: "; 308 sMessage += ::rtl::OString( sName.getStr(), sName.getLength(), osl_getThreadTextEncoding() ); 309 sMessage += "\nMode: 0x"; 310 if ( _nMode < 16 ) 311 sMessage += "0"; 312 sMessage += ::rtl::OString::valueOf( _nMode, 16 ).toAsciiUpperCase(); 313 OSL_ENSURE( false, sMessage.getStr() ); 314 #endif 315 StorageContainer::throwJavaException(e,env); 316 } 317 } 318 } 319 } 320 return pHelper; 321 } 322 // ----------------------------------------------------------------------------- 323 void StorageContainer::revokeStream( JNIEnv * env,jstring name, jstring key) 324 { 325 TStorages& rMap = lcl_getStorageMap(); 326 TStorages::iterator aFind = rMap.find(jstring2ustring(env,key)); 327 OSL_ENSURE(aFind != rMap.end(),"Storage could not be found in list!"); 328 if ( aFind != rMap.end() ) 329 aFind->second.second.erase(removeURLPrefix(jstring2ustring(env,name),aFind->second.first.second)); 330 } 331 // ----------------------------------------------------------------------------- 332 TStreamMap::mapped_type StorageContainer::getRegisteredStream( JNIEnv * env,jstring name, jstring key) 333 { 334 TStreamMap::mapped_type pRet; 335 TStorages& rMap = lcl_getStorageMap(); 336 TStorages::iterator aFind = rMap.find(jstring2ustring(env,key)); 337 OSL_ENSURE(aFind != rMap.end(),"Storage could not be found in list!"); 338 if ( aFind != rMap.end() ) 339 { 340 TStreamMap::iterator aStreamFind = aFind->second.second.find(removeURLPrefix(jstring2ustring(env,name),aFind->second.first.second)); 341 if ( aStreamFind != aFind->second.second.end() ) 342 pRet = aStreamFind->second; 343 } 344 345 return pRet; 346 } 347 // ----------------------------------------------------------------------------- 348 void StorageContainer::throwJavaException(const Exception& _aException,JNIEnv * env) 349 { 350 if (JNI_FALSE != env->ExceptionCheck()) 351 env->ExceptionClear(); 352 ::rtl::OString cstr( ::rtl::OUStringToOString(_aException.Message, RTL_TEXTENCODING_JAVA_UTF8 ) ); 353 OSL_TRACE( __FILE__": forwarding Exception: %s", cstr.getStr() ); 354 env->ThrowNew(env->FindClass("java/io/IOException"), cstr.getStr()); 355 } 356 //........................................................................ 357 } // namespace hsqldb 358 //........................................................................ 359 //........................................................................ 360 } 361 // namespace connectivity 362 //........................................................................ 363