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