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