1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <hsqldb/HStorageMap.hxx>
21 #include <comphelper/types.hxx>
22 #include <com/sun/star/embed/XTransactionBroadcaster.hpp>
23 #include <com/sun/star/embed/XTransactedObject.hpp>
24 #include <com/sun/star/embed/ElementModes.hpp>
25 #include <com/sun/star/lang/DisposedException.hpp>
26 #include <osl/diagnose.h>
27 #include <sal/log.hxx>
28 #include <uno/mapping.hxx>
30 #include <tools/diagnose_ex.h>
32 namespace connectivity::hsqldb
35 using namespace ::com::sun::star::uno
;
36 using namespace ::com::sun::star::lang
;
37 using namespace ::com::sun::star::embed
;
38 using namespace ::com::sun::star::io
;
40 StreamHelper::StreamHelper(const Reference
< XStream
>& _xStream
)
45 StreamHelper::~StreamHelper()
51 if ( m_xInputStream
.is() )
53 m_xInputStream
->closeInput();
54 m_xInputStream
.clear();
56 // this is done implicitly by the closing of the input stream
57 else if ( m_xOutputStream
.is() )
59 m_xOutputStream
->closeOutput();
62 ::comphelper::disposeComponent(m_xOutputStream
);
64 catch(const DisposedException
&)
67 catch(const Exception
&)
69 OSL_FAIL("Could not dispose OutputStream");
71 m_xOutputStream
.clear();
74 catch(const Exception
&)
76 TOOLS_WARN_EXCEPTION( "connectivity.hsqldb", "");
80 Reference
< XInputStream
> const & StreamHelper::getInputStream()
82 if ( !m_xInputStream
.is() )
83 m_xInputStream
= m_xStream
->getInputStream();
84 return m_xInputStream
;
87 Reference
< XOutputStream
> const & StreamHelper::getOutputStream()
89 if ( !m_xOutputStream
.is() )
90 m_xOutputStream
= m_xStream
->getOutputStream();
91 return m_xOutputStream
;
94 Reference
< XSeekable
> const & StreamHelper::getSeek()
97 m_xSeek
.set(m_xStream
,UNO_QUERY
);
101 css::uno::Reference
<css::embed::XStorage
> StorageData::mapStorage()
104 css::uno::Environment
env(css::uno::Environment::getCurrent());
105 if (!(env
.is() && storageEnvironment
.is())) {
106 throw css::uno::RuntimeException("cannot get environments");
108 if (env
.get() == storageEnvironment
.get()) {
111 css::uno::Mapping
map(storageEnvironment
, env
);
113 throw css::uno::RuntimeException("cannot get mapping");
115 css::uno::Reference
<css::embed::XStorage
> mapped
;
117 reinterpret_cast<void **>(&mapped
), storage
.get(),
118 cppu::UnoType
<css::embed::XStorage
>::get());
123 static TStorages
& lcl_getStorageMap()
125 static TStorages s_aMap
;
129 static OUString
lcl_getNextCount()
131 static sal_Int32 s_nCount
= 0;
132 return OUString::number(s_nCount
++);
135 OUString
StorageContainer::removeURLPrefix(const OUString
& _sURL
,const OUString
& _sFileURL
)
137 return _sURL
.copy(_sFileURL
.getLength()+1);
140 OUString
StorageContainer::removeOldURLPrefix(const OUString
& _sURL
)
142 OUString sRet
= _sURL
;
144 sal_Int32 nIndex
= sRet
.lastIndexOf('\\');
146 sal_Int32 nIndex
= sRet
.lastIndexOf('/');
150 sRet
= _sURL
.copy(nIndex
+1);
155 /*****************************************************************************/
156 /* convert jstring to rtl_uString */
158 OUString
StorageContainer::jstring2ustring(JNIEnv
* env
, jstring jstr
)
160 if (env
->ExceptionCheck())
162 env
->ExceptionClear();
163 OSL_FAIL("ExceptionClear");
168 jboolean
bCopy(true);
169 const jchar
* pChar
= env
->GetStringChars(jstr
,&bCopy
);
170 jsize len
= env
->GetStringLength(jstr
);
172 reinterpret_cast<sal_Unicode
const *>(pChar
), len
);
175 env
->ReleaseStringChars(jstr
,pChar
);
178 if (env
->ExceptionCheck())
180 env
->ExceptionClear();
181 OSL_FAIL("ExceptionClear");
187 OUString
StorageContainer::registerStorage(const Reference
< XStorage
>& _xStorage
,const OUString
& _sURL
)
189 OSL_ENSURE(_xStorage
.is(),"Storage is NULL!");
190 TStorages
& rMap
= lcl_getStorageMap();
191 // check if the storage is already in our map
192 TStorages::const_iterator aFind
= std::find_if(rMap
.begin(),rMap
.end(),
193 [&_xStorage
] (const TStorages::value_type
& storage
) {
194 return storage
.second
.mapStorage() == _xStorage
;
197 if ( aFind
== rMap
.end() )
199 aFind
= rMap
.insert(TStorages::value_type(lcl_getNextCount(), {_xStorage
, css::uno::Environment::getCurrent(), _sURL
, TStreamMap()})).first
;
205 TStorages::mapped_type
StorageContainer::getRegisteredStorage(const OUString
& _sKey
)
207 TStorages::mapped_type aRet
;
208 TStorages
& rMap
= lcl_getStorageMap();
209 TStorages::const_iterator aFind
= rMap
.find(_sKey
);
210 OSL_ENSURE(aFind
!= rMap
.end(),"Storage could not be found in list!");
211 if ( aFind
!= rMap
.end() )
212 aRet
= aFind
->second
;
217 OUString
StorageContainer::getRegisteredKey(const Reference
< XStorage
>& _xStorage
)
220 OSL_ENSURE(_xStorage
.is(),"Storage is NULL!");
221 TStorages
& rMap
= lcl_getStorageMap();
222 // check if the storage is already in our map
223 TStorages::const_iterator aFind
= std::find_if(rMap
.begin(),rMap
.end(),
224 [&_xStorage
] (const TStorages::value_type
& storage
) {
225 return storage
.second
.mapStorage() == _xStorage
;
228 if ( aFind
!= rMap
.end() )
233 void StorageContainer::revokeStorage(const OUString
& _sKey
,const Reference
<XTransactionListener
>& _xListener
)
235 TStorages
& rMap
= lcl_getStorageMap();
236 TStorages::iterator aFind
= rMap
.find(_sKey
);
237 if ( aFind
== rMap
.end() )
242 if ( _xListener
.is() )
244 Reference
<XTransactionBroadcaster
> xBroad(aFind
->second
.mapStorage(),UNO_QUERY
);
246 xBroad
->removeTransactionListener(_xListener
);
247 Reference
<XTransactedObject
> xTrans(aFind
->second
.mapStorage(),UNO_QUERY
);
252 catch(const Exception
&)
258 TStreamMap::mapped_type
StorageContainer::registerStream(JNIEnv
* env
,jstring name
, jstring key
,sal_Int32 _nMode
)
260 TStreamMap::mapped_type pHelper
;
261 TStorages
& rMap
= lcl_getStorageMap();
262 OUString sKey
= jstring2ustring(env
,key
);
263 TStorages::iterator aFind
= rMap
.find(sKey
);
264 OSL_ENSURE(aFind
!= rMap
.end(),"Storage could not be found in list!");
265 if ( aFind
!= rMap
.end() )
267 TStorages::mapped_type aStoragePair
= StorageContainer::getRegisteredStorage(sKey
);
268 auto storage
= aStoragePair
.mapStorage();
269 OSL_ENSURE(storage
.is(),"No Storage available!");
272 OUString sOrgName
= StorageContainer::jstring2ustring(env
,name
);
273 OUString sName
= removeURLPrefix(sOrgName
,aStoragePair
.url
);
274 TStreamMap::iterator aStreamFind
= aFind
->second
.streams
.find(sName
);
275 OSL_ENSURE( aStreamFind
== aFind
->second
.streams
.end(),"A Stream was already registered for this object!");
276 if ( aStreamFind
!= aFind
->second
.streams
.end() )
278 pHelper
= aStreamFind
->second
;
286 pHelper
= std::make_shared
<StreamHelper
>(storage
->openStreamElement(sName
,_nMode
));
288 catch(const Exception
&)
290 OUString sStrippedName
= removeOldURLPrefix(sOrgName
);
292 if ( (_nMode
& ElementModes::WRITE
) != ElementModes::WRITE
)
294 bool bIsStream
= true;
297 bIsStream
= storage
->isStreamElement(sStrippedName
);
299 catch(const Exception
&)
304 return pHelper
; // readonly file without data stream
306 pHelper
= std::make_shared
<StreamHelper
>(storage
->openStreamElement( sStrippedName
, _nMode
) );
308 aFind
->second
.streams
.emplace(sName
,pHelper
);
310 catch(const Exception
& e
)
312 TOOLS_WARN_EXCEPTION( "connectivity.hsqldb", "[HSQLDB-SDBC] caught an exception while opening a stream\n"
314 << "\nMode: 0x" << ( _nMode
< 16 ? "0" : "")
315 << std::hex
<< _nMode
);
316 StorageContainer::throwJavaException(e
,env
);
324 void StorageContainer::revokeStream( JNIEnv
* env
,jstring name
, jstring key
)
326 TStorages
& rMap
= lcl_getStorageMap();
327 TStorages::iterator aFind
= rMap
.find(jstring2ustring(env
,key
));
328 OSL_ENSURE(aFind
!= rMap
.end(),"Storage could not be found in list!");
329 if ( aFind
!= rMap
.end() )
330 aFind
->second
.streams
.erase(removeURLPrefix(jstring2ustring(env
,name
),aFind
->second
.url
));
333 TStreamMap::mapped_type
StorageContainer::getRegisteredStream( JNIEnv
* env
,jstring name
, jstring key
)
335 TStreamMap::mapped_type pRet
;
336 TStorages
& rMap
= lcl_getStorageMap();
337 TStorages::const_iterator aFind
= rMap
.find(jstring2ustring(env
,key
));
338 OSL_ENSURE(aFind
!= rMap
.end(),"Storage could not be found in list!");
339 if ( aFind
!= rMap
.end() )
341 TStreamMap::const_iterator aStreamFind
= aFind
->second
.streams
.find(removeURLPrefix(jstring2ustring(env
,name
),aFind
->second
.url
));
342 if ( aStreamFind
!= aFind
->second
.streams
.end() )
343 pRet
= aStreamFind
->second
;
349 void StorageContainer::throwJavaException(const Exception
& _aException
,JNIEnv
* env
)
351 if (env
->ExceptionCheck())
352 env
->ExceptionClear();
353 SAL_WARN("connectivity.hsqldb", "forwarding Exception: " << _aException
);
354 OString
cstr( OUStringToOString(_aException
.Message
, RTL_TEXTENCODING_JAVA_UTF8
) );
355 env
->ThrowNew(env
->FindClass("java/io/IOException"), cstr
.getStr());
361 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */