LibreOffice Module connectivity (master) 1
HStorageMap.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
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>
29#include <algorithm>
31
33{
34
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;
39
40 StreamHelper::StreamHelper(const Reference< XStream>& _xStream)
41 : m_xStream(_xStream)
42 {
43 }
44
46 {
47 try
48 {
49 m_xStream.clear();
50 m_xSeek.clear();
51 if ( m_xInputStream.is() )
52 {
53 m_xInputStream->closeInput();
54 m_xInputStream.clear();
55 }
56 // this is done implicitly by the closing of the input stream
57 else if ( m_xOutputStream.is() )
58 {
59 m_xOutputStream->closeOutput();
60 try
61 {
62 ::comphelper::disposeComponent(m_xOutputStream);
63 }
64 catch(const DisposedException&)
65 {
66 }
67 catch(const Exception&)
68 {
69 OSL_FAIL("Could not dispose OutputStream");
70 }
71 m_xOutputStream.clear();
72 }
73 }
74 catch(const Exception&)
75 {
76 TOOLS_WARN_EXCEPTION( "connectivity.hsqldb", "");
77 }
78 }
79
80 Reference< XInputStream> const & StreamHelper::getInputStream()
81 {
82 if ( !m_xInputStream.is() )
83 m_xInputStream = m_xStream->getInputStream();
84 return m_xInputStream;
85 }
86
87 Reference< XOutputStream> const & StreamHelper::getOutputStream()
88 {
89 if ( !m_xOutputStream.is() )
90 m_xOutputStream = m_xStream->getOutputStream();
91 return m_xOutputStream;
92 }
93
94 Reference< XSeekable> const & StreamHelper::getSeek()
95 {
96 if ( !m_xSeek.is() )
97 m_xSeek.set(m_xStream,UNO_QUERY);
98 return m_xSeek;
99 }
100
101 css::uno::Reference<css::embed::XStorage> StorageData::mapStorage()
102 const
103 {
104 css::uno::Environment env(css::uno::Environment::getCurrent());
105 if (!(env.is() && storageEnvironment.is())) {
106 throw css::uno::RuntimeException("cannot get environments");
107 }
108 if (env.get() == storageEnvironment.get()) {
109 return storage;
110 } else {
111 css::uno::Mapping map(storageEnvironment, env);
112 if (!map.is()) {
113 throw css::uno::RuntimeException("cannot get mapping");
114 }
115 css::uno::Reference<css::embed::XStorage> mapped;
116 map.mapInterface(
117 reinterpret_cast<void **>(&mapped), storage.get(),
119 return mapped;
120 }
121 }
122
124 {
125 static TStorages s_aMap;
126 return s_aMap;
127 }
128
129 static OUString lcl_getNextCount()
130 {
131 static sal_Int32 s_nCount = 0;
132 return OUString::number(s_nCount++);
133 }
134
135 OUString StorageContainer::removeURLPrefix(std::u16string_view _sURL, std::u16string_view _sFileURL)
136 {
137 return OUString(_sURL.substr(_sFileURL.size()+1));
138 }
139
140 OUString StorageContainer::removeOldURLPrefix(const OUString& _sURL)
141 {
142 OUString sRet = _sURL;
143#if defined(_WIN32)
144 sal_Int32 nIndex = sRet.lastIndexOf('\\');
145#else
146 sal_Int32 nIndex = sRet.lastIndexOf('/');
147#endif
148 if ( nIndex != -1 )
149 {
150 sRet = _sURL.copy(nIndex+1);
151 }
152 return sRet;
153
154 }
155 /*****************************************************************************/
156 /* convert jstring to rtl_uString */
157
158 OUString StorageContainer::jstring2ustring(JNIEnv * env, jstring jstr)
159 {
160 if (env->ExceptionCheck())
161 {
162 env->ExceptionClear();
163 OSL_FAIL("ExceptionClear");
164 }
165 OUString aStr;
166 if ( jstr )
167 {
168 jboolean bCopy(true);
169 const jchar* pChar = env->GetStringChars(jstr,&bCopy);
170 jsize len = env->GetStringLength(jstr);
171 aStr = OUString(
172 reinterpret_cast<sal_Unicode const *>(pChar), len);
173
174 if(bCopy)
175 env->ReleaseStringChars(jstr,pChar);
176 }
177
178 if (env->ExceptionCheck())
179 {
180 env->ExceptionClear();
181 OSL_FAIL("ExceptionClear");
182 }
183 return aStr;
184 }
185
186
187 OUString StorageContainer::registerStorage(const Reference< XStorage>& _xStorage,const OUString& _sURL)
188 {
189 OSL_ENSURE(_xStorage.is(),"Storage is NULL!");
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;
195 });
196
197 if ( aFind == rMap.end() )
198 {
199 aFind = rMap.insert(TStorages::value_type(lcl_getNextCount(), {_xStorage, css::uno::Environment::getCurrent(), _sURL, TStreamMap()})).first;
200 }
201
202 return aFind->first;
203 }
204
205 TStorages::mapped_type StorageContainer::getRegisteredStorage(const OUString& _sKey)
206 {
207 TStorages::mapped_type aRet;
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;
213
214 return aRet;
215 }
216
217 OUString StorageContainer::getRegisteredKey(const Reference< XStorage>& _xStorage)
218 {
219 OUString sKey;
220 OSL_ENSURE(_xStorage.is(),"Storage is NULL!");
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;
226 });
227
228 if ( aFind != rMap.end() )
229 sKey = aFind->first;
230 return sKey;
231 }
232
233 void StorageContainer::revokeStorage(const OUString& _sKey,const Reference<XTransactionListener>& _xListener)
234 {
236 TStorages::iterator aFind = rMap.find(_sKey);
237 if ( aFind == rMap.end() )
238 return;
239
240 try
241 {
242 if ( _xListener.is() )
243 {
244 Reference<XTransactionBroadcaster> xBroad(aFind->second.mapStorage(),UNO_QUERY);
245 if ( xBroad.is() )
246 xBroad->removeTransactionListener(_xListener);
247 Reference<XTransactedObject> xTrans(aFind->second.mapStorage(),UNO_QUERY);
248 if ( xTrans.is() )
249 xTrans->commit();
250 }
251 }
252 catch(const Exception&)
253 {
254 }
255 rMap.erase(aFind);
256 }
257
258 TStreamMap::mapped_type StorageContainer::registerStream(JNIEnv * env,jstring name, jstring key,sal_Int32 _nMode)
259 {
260 TStreamMap::mapped_type pHelper;
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() )
266 {
267 TStorages::mapped_type aStoragePair = StorageContainer::getRegisteredStorage(sKey);
268 auto storage = aStoragePair.mapStorage();
269 OSL_ENSURE(storage.is(),"No Storage available!");
270 if ( storage.is() )
271 {
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() )
277 {
278 pHelper = aStreamFind->second;
279 }
280 else
281 {
282 try
283 {
284 try
285 {
286 pHelper = std::make_shared<StreamHelper>(storage->openStreamElement(sName,_nMode));
287 }
288 catch(const Exception&)
289 {
290 OUString sStrippedName = removeOldURLPrefix(sOrgName);
291
292 if ( (_nMode & ElementModes::WRITE) != ElementModes::WRITE )
293 {
294 bool bIsStream = true;
295 try
296 {
297 bIsStream = storage->isStreamElement(sStrippedName);
298 }
299 catch(const Exception&)
300 {
301 bIsStream = false;
302 }
303 if ( !bIsStream )
304 return pHelper; // readonly file without data stream
305 }
306 pHelper = std::make_shared<StreamHelper>(storage->openStreamElement( sStrippedName, _nMode ) );
307 }
308 aFind->second.streams.emplace(sName,pHelper);
309 }
310 catch(const Exception& e)
311 {
312 TOOLS_WARN_EXCEPTION( "connectivity.hsqldb", "[HSQLDB-SDBC] caught an exception while opening a stream\n"
313 "Name: " << sName
314 << "\nMode: 0x" << ( _nMode < 16 ? "0" : "")
315 << std::hex << _nMode );
317 }
318 }
319 }
320 }
321 return pHelper;
322 }
323
324 void StorageContainer::revokeStream( JNIEnv * env,jstring name, jstring key)
325 {
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));
331 }
332
333 TStreamMap::mapped_type StorageContainer::getRegisteredStream( JNIEnv * env,jstring name, jstring key)
334 {
335 TStreamMap::mapped_type pRet;
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() )
340 {
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;
344 }
345
346 return pRet;
347 }
348
349 void StorageContainer::throwJavaException(const Exception& _aException,JNIEnv * env)
350 {
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());
356 }
357
358} // namespace
359
360
361/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static OUString registerStorage(const css::uno::Reference< css::embed::XStorage > &_xStorage, const OUString &_sURL)
static TStreamMap::mapped_type registerStream(JNIEnv *env, jstring name, jstring key, sal_Int32 _nMode)
static void throwJavaException(const css::uno::Exception &_aException, JNIEnv *env)
static void revokeStorage(const OUString &_sKey, const css::uno::Reference< css::embed::XTransactionListener > &_xListener)
static OUString getRegisteredKey(const css::uno::Reference< css::embed::XStorage > &_xStorage)
static OUString jstring2ustring(JNIEnv *env, jstring jstr)
static OUString removeOldURLPrefix(const OUString &_sURL)
static OUString removeURLPrefix(std::u16string_view _sURL, std::u16string_view _sFileURL)
static void revokeStream(JNIEnv *env, jstring name, jstring key)
static TStreamMap::mapped_type getRegisteredStream(JNIEnv *env, jstring name, jstring key)
static TStorages::mapped_type getRegisteredStorage(const OUString &_sKey)
css::uno::Reference< css::io::XOutputStream > m_xOutputStream
Definition: HStorageMap.hxx:50
css::uno::Reference< css::io::XSeekable > const & getSeek()
Definition: HStorageMap.cxx:94
css::uno::Reference< css::io::XStream > m_xStream
Definition: HStorageMap.hxx:48
css::uno::Reference< css::io::XSeekable > m_xSeek
Definition: HStorageMap.hxx:49
css::uno::Reference< css::io::XInputStream > m_xInputStream
Definition: HStorageMap.hxx:51
css::uno::Reference< css::io::XInputStream > const & getInputStream()
Definition: HStorageMap.cxx:80
StreamHelper(const css::uno::Reference< css::io::XStream > &_xStream)
Definition: HStorageMap.cxx:40
css::uno::Reference< css::io::XOutputStream > const & getOutputStream()
Definition: HStorageMap.cxx:87
#define TOOLS_WARN_EXCEPTION(area, stream)
OUString sName
sal_Int32 nIndex
#define SAL_WARN(area, stream)
const css::uno::Reference< css::xml::crypto::XSecurityEnvironment > & env
aStr
@ Exception
std::map< OUString, StorageData > TStorages
Definition: HStorageMap.hxx:73
std::map< OUString, std::shared_ptr< StreamHelper > > TStreamMap
Definition: HStorageMap.hxx:62
static TStorages & lcl_getStorageMap()
static OUString lcl_getNextCount()
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
Definition: pq_tools.cxx:100
OUString name
Definition: pq_statics.cxx:74
std::map< OUString, rtl::Reference< Entity > > map
css::uno::Reference< css::embed::XStorage > mapStorage() const
css::uno::Reference< css::embed::XStorage > storage
Definition: HStorageMap.hxx:65
css::uno::Environment storageEnvironment
Definition: HStorageMap.hxx:66
sal_uInt16 sal_Unicode
Reference< XStream > m_xStream
const char * pChar