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