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 #include <com/sun/star/beans/PropertyValue.hpp>
20 #include <ReportEngineJFree.hxx>
21 #include <comphelper/documentconstants.hxx>
22 #include <comphelper/storagehelper.hxx>
23 #include <connectivity/dbtools.hxx>
24 #include <comphelper/mimeconfighelper.hxx>
25 #include <comphelper/string.hxx>
26 #include <cppuhelper/supportsservice.hxx>
27 #include <com/sun/star/beans/PropertyAttribute.hpp>
28 #include <com/sun/star/beans/NamedValue.hpp>
29 #include <com/sun/star/frame/Desktop.hpp>
30 #include <com/sun/star/frame/XComponentLoader.hpp>
31 #include <com/sun/star/frame/FrameSearchFlag.hpp>
32 #include <com/sun/star/embed/XTransactedObject.hpp>
33 #include <com/sun/star/sdb/XCompletedExecution.hpp>
34 #include <com/sun/star/sdb/XSingleSelectQueryAnalyzer.hpp>
35 #include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp>
36 #include <com/sun/star/sdb/CommandType.hpp>
37 
38 #include <com/sun/star/task/XInteractionHandler.hpp>
39 #include <com/sun/star/task/XJob.hpp>
40 
41 #include <unotools/useroptions.hxx>
42 #include <unotools/tempfile.hxx>
43 #include <unotools/sharedunocomponent.hxx>
44 
45 #include <Tools.hxx>
46 #include <strings.hxx>
47 #include <strings.hrc>
48 #include <core_resource.hxx>
49 
50 #include <connectivity/CommonTools.hxx>
51 #include <rtl/ustrbuf.hxx>
52 #include <sfx2/docfilt.hxx>
53 
54 namespace reportdesign
55 {
56 
57     using namespace com::sun::star;
58     using namespace comphelper;
59 
60 
OReportEngineJFree(const uno::Reference<uno::XComponentContext> & context)61 OReportEngineJFree::OReportEngineJFree( const uno::Reference< uno::XComponentContext >& context)
62 :ReportEngineBase(m_aMutex)
63 ,ReportEnginePropertySet(context,IMPLEMENTS_PROPERTY_SET,uno::Sequence< OUString >())
64 ,m_xContext(context)
65 ,m_nMaxRows(0)
66 {
67 }
68 
69 // TODO: VirtualFunctionFinder: This is virtual function!
70 
~OReportEngineJFree()71 OReportEngineJFree::~OReportEngineJFree()
72 {
73 }
74 
IMPLEMENT_FORWARD_XINTERFACE2(OReportEngineJFree,ReportEngineBase,ReportEnginePropertySet)75 IMPLEMENT_FORWARD_XINTERFACE2(OReportEngineJFree,ReportEngineBase,ReportEnginePropertySet)
76 
77 void SAL_CALL OReportEngineJFree::dispose()
78 {
79     ReportEnginePropertySet::dispose();
80     cppu::WeakComponentImplHelperBase::dispose();
81     m_xActiveConnection.clear();
82 }
83 
getImplementationName_Static()84 OUString OReportEngineJFree::getImplementationName_Static(  )
85 {
86     return "com.sun.star.comp.report.OReportEngineJFree";
87 }
88 
89 
getImplementationName()90 OUString SAL_CALL OReportEngineJFree::getImplementationName(  )
91 {
92     return getImplementationName_Static();
93 }
94 
getSupportedServiceNames_Static()95 uno::Sequence< OUString > OReportEngineJFree::getSupportedServiceNames_Static(  )
96 {
97     uno::Sequence< OUString > aServices { "com.sun.star.report.ReportEngine" };
98 
99     return aServices;
100 }
101 
create(uno::Reference<uno::XComponentContext> const & xContext)102 uno::Reference< uno::XInterface > OReportEngineJFree::create(uno::Reference< uno::XComponentContext > const & xContext)
103 {
104     return *(new OReportEngineJFree(xContext));
105 }
106 
107 
getSupportedServiceNames()108 uno::Sequence< OUString > SAL_CALL OReportEngineJFree::getSupportedServiceNames(  )
109 {
110     return getSupportedServiceNames_Static();
111 }
112 
supportsService(const OUString & ServiceName)113 sal_Bool SAL_CALL OReportEngineJFree::supportsService(const OUString& ServiceName)
114 {
115     return cppu::supportsService(this, ServiceName);
116 }
117 
118 // XReportEngine
119     // Attributes
getReportDefinition()120 uno::Reference< report::XReportDefinition > SAL_CALL OReportEngineJFree::getReportDefinition()
121 {
122     ::osl::MutexGuard aGuard(m_aMutex);
123     return m_xReport;
124 }
125 
setReportDefinition(const uno::Reference<report::XReportDefinition> & _report)126 void SAL_CALL OReportEngineJFree::setReportDefinition( const uno::Reference< report::XReportDefinition >& _report )
127 {
128     if ( !_report.is() )
129         throw lang::IllegalArgumentException();
130     BoundListeners l;
131     {
132         ::osl::MutexGuard aGuard(m_aMutex);
133         if ( m_xReport != _report )
134         {
135             prepareSet(PROPERTY_REPORTDEFINITION, uno::makeAny(m_xReport), uno::makeAny(_report), &l);
136             m_xReport = _report;
137         }
138     }
139     l.notify();
140 }
141 
getStatusIndicator()142 uno::Reference< task::XStatusIndicator > SAL_CALL OReportEngineJFree::getStatusIndicator()
143 {
144     ::osl::MutexGuard aGuard(m_aMutex);
145     return m_StatusIndicator;
146 }
147 
setStatusIndicator(const uno::Reference<task::XStatusIndicator> & _statusindicator)148 void SAL_CALL OReportEngineJFree::setStatusIndicator( const uno::Reference< task::XStatusIndicator >& _statusindicator )
149 {
150     set(PROPERTY_STATUSINDICATOR,_statusindicator,m_StatusIndicator);
151 }
152 
getNewOutputName()153 OUString OReportEngineJFree::getNewOutputName()
154 {
155     ::osl::MutexGuard aGuard(m_aMutex);
156     ::connectivity::checkDisposed(ReportEngineBase::rBHelper.bDisposed);
157     if ( !m_xReport.is() || !m_xActiveConnection.is() )
158         throw lang::IllegalArgumentException();
159 
160     static const char s_sMediaType[] = "MediaType";
161 
162     MimeConfigurationHelper aConfighelper(m_xContext);
163     const OUString sMimeType = m_xReport->getMimeType();
164     std::shared_ptr<const SfxFilter> pFilter = SfxFilter::GetDefaultFilter( aConfighelper.GetDocServiceNameFromMediaType(sMimeType) );
165     OUString sExt(".rpt");
166     if ( pFilter )
167         sExt = ::comphelper::string::stripStart(pFilter->GetDefaultExtension(), '*');
168 
169     uno::Reference< embed::XStorage > xTemp = OStorageHelper::GetTemporaryStorage(/*sFileTemp,embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE,*/ m_xContext);
170     utl::DisposableComponent aTemp(xTemp);
171     uno::Sequence< beans::PropertyValue > aEmpty;
172     uno::Reference< beans::XPropertySet> xStorageProp(xTemp,uno::UNO_QUERY);
173     if ( xStorageProp.is() )
174     {
175         xStorageProp->setPropertyValue( s_sMediaType, uno::makeAny(sMimeType));
176     }
177     m_xReport->storeToStorage(xTemp,aEmpty); // store to temp file because it may contain information which isn't in the database yet.
178 
179     uno::Sequence< beans::NamedValue > aConvertedProperties(8);
180     sal_Int32 nPos = 0;
181     aConvertedProperties[nPos].Name = "InputStorage";
182     aConvertedProperties[nPos++].Value <<= xTemp;
183     aConvertedProperties[nPos].Name = "OutputStorage";
184 
185     OUString sFileURL;
186     OUString sName = m_xReport->getCaption();
187     if ( sName.isEmpty() )
188         sName = m_xReport->getName();
189     {
190         ::utl::TempFile aTestFile(sName, false, &sExt);
191         if ( !aTestFile.IsValid() )
192         {
193             sName = RptResId(RID_STR_REPORT);
194             ::utl::TempFile aFile(sName, false, &sExt);
195             sFileURL = aFile.GetURL();
196         }
197         else
198             sFileURL = aTestFile.GetURL();
199     }
200 
201     uno::Reference< embed::XStorage > xOut = OStorageHelper::GetStorageFromURL(sFileURL,embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE, m_xContext);
202     utl::DisposableComponent aOut(xOut);
203     xStorageProp.set(xOut,uno::UNO_QUERY);
204     if ( xStorageProp.is() )
205     {
206         xStorageProp->setPropertyValue( s_sMediaType, uno::makeAny(sMimeType));
207     }
208 
209     aConvertedProperties[nPos++].Value <<= xOut;
210 
211     aConvertedProperties[nPos].Name = PROPERTY_REPORTDEFINITION;
212     aConvertedProperties[nPos++].Value <<= m_xReport;
213 
214     aConvertedProperties[nPos].Name = PROPERTY_ACTIVECONNECTION;
215     aConvertedProperties[nPos++].Value <<= m_xActiveConnection;
216 
217     aConvertedProperties[nPos].Name = PROPERTY_MAXROWS;
218     aConvertedProperties[nPos++].Value <<= m_nMaxRows;
219 
220     // some meta data
221     SvtUserOptions aUserOpts;
222     OUStringBuffer sAuthor(aUserOpts.GetFirstName());
223     sAuthor.append(" ");
224     sAuthor.append(aUserOpts.GetLastName());
225     aConvertedProperties[nPos].Name = "Author";
226     aConvertedProperties[nPos++].Value <<= sAuthor.makeStringAndClear();
227 
228     aConvertedProperties[nPos].Name = "Title";
229     aConvertedProperties[nPos++].Value <<= m_xReport->getCaption();
230 
231     OUString sOutputName;
232 
233     // create job factory and initialize
234     const OUString sReportEngineServiceName = ::dbtools::getDefaultReportEngineServiceName(m_xContext);
235     uno::Reference<task::XJob> xJob(m_xContext->getServiceManager()->createInstanceWithContext(sReportEngineServiceName,m_xContext),uno::UNO_QUERY_THROW);
236     if ( !m_xReport->getCommand().isEmpty() )
237     {
238         xJob->execute(aConvertedProperties);
239         if ( xStorageProp.is() )
240         {
241              sOutputName = sFileURL;
242         }
243     }
244 
245     uno::Reference<embed::XTransactedObject> xTransact(xOut,uno::UNO_QUERY);
246     if ( !sOutputName.isEmpty() && xTransact.is() )
247         xTransact->commit();
248 
249     if ( sOutputName.isEmpty() )
250         throw lang::IllegalArgumentException();
251 
252     return sOutputName;
253 }
254 
255 // Methods
createDocumentModel()256 uno::Reference< frame::XModel > SAL_CALL OReportEngineJFree::createDocumentModel( )
257 {
258     return createDocumentAlive(nullptr,true);
259 }
260 
createDocumentAlive(const uno::Reference<frame::XFrame> & _frame)261 uno::Reference< frame::XModel > SAL_CALL OReportEngineJFree::createDocumentAlive( const uno::Reference< frame::XFrame >& _frame )
262 {
263     return createDocumentAlive(_frame,false);
264 }
265 
createDocumentAlive(const uno::Reference<frame::XFrame> & _frame,bool _bHidden)266 uno::Reference< frame::XModel > OReportEngineJFree::createDocumentAlive( const uno::Reference< frame::XFrame >& _frame,bool _bHidden )
267 {
268     uno::Reference< frame::XModel > xModel;
269     OUString sOutputName = getNewOutputName(); // starts implicitly the report generator
270     if ( !sOutputName.isEmpty() )
271     {
272         ::osl::MutexGuard aGuard(m_aMutex);
273         ::connectivity::checkDisposed(ReportEngineBase::rBHelper.bDisposed);
274         uno::Reference<frame::XComponentLoader> xFrameLoad(_frame,uno::UNO_QUERY);
275         if ( !xFrameLoad.is() )
276         {
277             // if there is no frame given, find the right
278             xFrameLoad = frame::Desktop::create(m_xContext);
279             sal_Int32 const nFrameSearchFlag = frame::FrameSearchFlag::TASKS | frame::FrameSearchFlag::CREATE;
280             uno::Reference< frame::XFrame> xFrame = uno::Reference< frame::XFrame>(xFrameLoad,uno::UNO_QUERY_THROW)->findFrame("_blank",nFrameSearchFlag);
281             xFrameLoad.set( xFrame,uno::UNO_QUERY);
282         }
283 
284         if ( xFrameLoad.is() )
285         {
286             uno::Sequence < beans::PropertyValue > aArgs( _bHidden ? 3 : 2 );
287             sal_Int32 nLen = 0;
288             aArgs[nLen].Name = "AsTemplate";
289             aArgs[nLen++].Value <<= false;
290 
291             aArgs[nLen].Name = "ReadOnly";
292             aArgs[nLen++].Value <<= true;
293 
294             if ( _bHidden )
295             {
296                 aArgs[nLen].Name = "Hidden";
297                 aArgs[nLen++].Value <<= true;
298             }
299 
300             xModel.set( xFrameLoad->loadComponentFromURL(
301                 sOutputName,
302                 OUString(), // empty frame name
303                 0,
304                 aArgs
305                 ),uno::UNO_QUERY);
306         }
307     }
308     return xModel;
309 }
310 
createDocument()311 util::URL SAL_CALL OReportEngineJFree::createDocument( )
312 {
313     util::URL aRet;
314     uno::Reference< frame::XModel > xModel = createDocumentModel();
315     if ( xModel.is() )
316     {
317         ::osl::MutexGuard aGuard(m_aMutex);
318         ::connectivity::checkDisposed(ReportEngineBase::rBHelper.bDisposed);
319     }
320     return aRet;
321 }
322 
interrupt()323 void SAL_CALL OReportEngineJFree::interrupt(  )
324 {
325     ::osl::MutexGuard aGuard(m_aMutex);
326     ::connectivity::checkDisposed(ReportEngineBase::rBHelper.bDisposed);
327 }
328 
getPropertySetInfo()329 uno::Reference< beans::XPropertySetInfo > SAL_CALL OReportEngineJFree::getPropertySetInfo(  )
330 {
331     return ReportEnginePropertySet::getPropertySetInfo();
332 }
333 
setPropertyValue(const OUString & aPropertyName,const uno::Any & aValue)334 void SAL_CALL OReportEngineJFree::setPropertyValue( const OUString& aPropertyName, const uno::Any& aValue )
335 {
336     ReportEnginePropertySet::setPropertyValue( aPropertyName, aValue );
337 }
338 
getPropertyValue(const OUString & PropertyName)339 uno::Any SAL_CALL OReportEngineJFree::getPropertyValue( const OUString& PropertyName )
340 {
341     return ReportEnginePropertySet::getPropertyValue( PropertyName);
342 }
343 
addPropertyChangeListener(const OUString & aPropertyName,const uno::Reference<beans::XPropertyChangeListener> & xListener)344 void SAL_CALL OReportEngineJFree::addPropertyChangeListener( const OUString& aPropertyName, const uno::Reference< beans::XPropertyChangeListener >& xListener )
345 {
346     ReportEnginePropertySet::addPropertyChangeListener( aPropertyName, xListener );
347 }
348 
removePropertyChangeListener(const OUString & aPropertyName,const uno::Reference<beans::XPropertyChangeListener> & aListener)349 void SAL_CALL OReportEngineJFree::removePropertyChangeListener( const OUString& aPropertyName, const uno::Reference< beans::XPropertyChangeListener >& aListener )
350 {
351     ReportEnginePropertySet::removePropertyChangeListener( aPropertyName, aListener );
352 }
353 
addVetoableChangeListener(const OUString & PropertyName,const uno::Reference<beans::XVetoableChangeListener> & aListener)354 void SAL_CALL OReportEngineJFree::addVetoableChangeListener( const OUString& PropertyName, const uno::Reference< beans::XVetoableChangeListener >& aListener )
355 {
356     ReportEnginePropertySet::addVetoableChangeListener( PropertyName, aListener );
357 }
358 
removeVetoableChangeListener(const OUString & PropertyName,const uno::Reference<beans::XVetoableChangeListener> & aListener)359 void SAL_CALL OReportEngineJFree::removeVetoableChangeListener( const OUString& PropertyName, const uno::Reference< beans::XVetoableChangeListener >& aListener )
360 {
361     ReportEnginePropertySet::removeVetoableChangeListener( PropertyName, aListener );
362 }
363 
getActiveConnection()364 uno::Reference< sdbc::XConnection > SAL_CALL OReportEngineJFree::getActiveConnection()
365 {
366     return m_xActiveConnection;
367 }
368 
setActiveConnection(const uno::Reference<sdbc::XConnection> & _activeconnection)369 void SAL_CALL OReportEngineJFree::setActiveConnection( const uno::Reference< sdbc::XConnection >& _activeconnection )
370 {
371     if ( !_activeconnection.is() )
372         throw lang::IllegalArgumentException();
373     set(PROPERTY_ACTIVECONNECTION,_activeconnection,m_xActiveConnection);
374 }
375 
getMaxRows()376 ::sal_Int32 SAL_CALL OReportEngineJFree::getMaxRows()
377 {
378     ::osl::MutexGuard aGuard(m_aMutex);
379     return m_nMaxRows;
380 }
381 
setMaxRows(::sal_Int32 MaxRows)382 void SAL_CALL OReportEngineJFree::setMaxRows( ::sal_Int32 MaxRows )
383 {
384     set(PROPERTY_MAXROWS,MaxRows,m_nMaxRows);
385 }
386 
387 } // namespace reportdesign
388 
389 
390 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
391