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
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_filter.hxx"
26 #include <filter/msfilter/msfiltertracer.hxx>
27 #include <vcl/svapp.hxx>
28 #include <tools/urlobj.hxx>
29 #include <com/sun/star/uno/Sequence.h>
30 #include <com/sun/star/util/logging/LogLevel.hpp>
31 #include <com/sun/star/util/SearchAlgorithms.hpp>
32 #include <com/sun/star/util/SearchFlags.hpp>
33 #include <comphelper/processfactory.hxx>
34 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
35 #include <com/sun/star/io/XActiveDataSource.hpp>
36 #include <svtools/FilterConfigItem.hxx>
37 #include <unotools/localfilehelper.hxx>
38 #include <unotools/streamwrap.hxx>
39 #include <unotools/ucbstreamhelper.hxx>
40
41
42 // --------------
43 // - Namespaces -
44 // --------------
45
46 using namespace ::com::sun::star;
47
MSFilterTracer(const::rtl::OUString & rConfigPath,uno::Sequence<beans::PropertyValue> * pConfigData)48 MSFilterTracer::MSFilterTracer( const ::rtl::OUString& rConfigPath, uno::Sequence< beans::PropertyValue >* pConfigData ) :
49 mpCfgItem( new FilterConfigItem( rConfigPath, pConfigData ) ),
50 mpAttributeList( new SvXMLAttributeList() ),
51 mpStream( NULL ),
52 mbEnabled( sal_False ) // will be set to true in StartTracing()
53 {
54 if ( mpCfgItem->ReadBool( rtl::OUString::createFromAscii( "On" ), sal_False ) )
55 {
56 uno::Reference< lang::XMultiServiceFactory > xMgr( ::comphelper::getProcessServiceFactory() );
57 if ( xMgr.is() )
58 {
59 /* the following methods try to read a property, if it is not available it will put the second
60 parameter as default into the property sequence of the FilterConfigItem. It means we ensure that
61 the property is available by trying to read it (the return value of the method is ignored) */
62 ::rtl::OUString aEmptyString;
63 mpCfgItem->ReadInt32( rtl::OUString::createFromAscii( "LogLevel" ), util::logging::LogLevel::ALL );
64 mpCfgItem->ReadString( rtl::OUString::createFromAscii( "ClassFilter" ), aEmptyString );
65 mpCfgItem->ReadString( rtl::OUString::createFromAscii( "MethodFilter" ), aEmptyString );
66 mpCfgItem->ReadString( rtl::OUString::createFromAscii( "MessageFilter" ), aEmptyString );
67 util::SearchAlgorithms eSearchAlgorithm = (util::SearchAlgorithms)
68 mpCfgItem->ReadInt32( rtl::OUString::createFromAscii( "SearchAlgorithm" ), util::SearchAlgorithms_ABSOLUTE );
69
70 // creating the name of the log file
71 rtl::OUString aPath( mpCfgItem->ReadString( rtl::OUString::createFromAscii( "Path" ), aEmptyString ) );
72 rtl::OUString aName( mpCfgItem->ReadString( rtl::OUString::createFromAscii( "Name" ), aEmptyString ) );
73 rtl::OUString aDocumentURL( mpCfgItem->ReadString( rtl::OUString::createFromAscii( "DocumentURL" ), aEmptyString ) );
74 INetURLObject aLogFile( aDocumentURL );
75 if ( aLogFile.GetMainURL( INetURLObject::NO_DECODE ).getLength() )
76 {
77 if ( aPath.getLength() )
78 {
79 String aOldName( aLogFile.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::NO_DECODE ) );
80 aLogFile = INetURLObject( aPath );
81 aLogFile.insertName( aOldName );
82 }
83 if ( aName.getLength() )
84 aLogFile.setName( aName );
85 }
86 else
87 {
88 if ( aPath.getLength() )
89 aLogFile = INetURLObject( aPath );
90 else
91 {
92 String aURLStr;
93 if( ::utl::LocalFileHelper::ConvertPhysicalNameToURL( Application::GetAppFileName(), aURLStr ) )
94 {
95 aLogFile = INetURLObject(aURLStr);
96 aLogFile .removeSegment();
97 aLogFile .removeFinalSlash();
98 }
99 }
100 if ( !aName.getLength() )
101 aName = rtl::OUString::createFromAscii( "tracer" );
102 aLogFile.insertName( aName );
103 }
104 aLogFile.setExtension( rtl::OUString::createFromAscii( "log" ) );
105
106 // creating the file stream
107 mpStream = ::utl::UcbStreamHelper::CreateStream( aLogFile.GetMainURL( INetURLObject::NO_DECODE ), STREAM_WRITE | STREAM_TRUNC | STREAM_SHARE_DENYNONE );
108 if ( mpStream && !mpStream->GetError() )
109 {
110 // creating a wrapper for our stream
111 utl::OOutputStreamWrapper* pHelper = new ::utl::OOutputStreamWrapper( *mpStream );
112 uno::Reference< io::XOutputStream > xOutputStream( pHelper );
113
114 // instanciating the DocumentHandler, then setting the OutputStream
115 mxHandler = uno::Reference< xml::sax::XDocumentHandler >( xMgr->createInstance( rtl::OUString::createFromAscii( "com.sun.star.xml.sax.Writer" ) ), uno::UNO_QUERY );
116 uno::Reference< io::XActiveDataSource > xDocSrc( mxHandler, uno::UNO_QUERY );
117 xDocSrc->setOutputStream( xOutputStream );
118 mxHandler->startDocument();
119 mxHandler->ignorableWhitespace ( rtl::OUString::createFromAscii( " " ) );
120
121 // writing the "DocumentHandler" property, so the FilterTracer component
122 // will use it for the output
123 uno::Any aAny;
124 aAny <<= xDocSrc;
125 mpCfgItem->WriteAny( rtl::OUString::createFromAscii( "DocumentHandler" ), aAny );
126
127 SvXMLAttributeList* pAttrList = new SvXMLAttributeList;
128 pAttrList->AddAttribute( rtl::OUString::createFromAscii( "DocumentURL" ), aDocumentURL );
129 uno::Reference < xml::sax::XAttributeList > xAttributeList(pAttrList);
130 mxHandler->startElement( rtl::OUString::createFromAscii( "Document" ), xAttributeList );
131 }
132
133 uno::Sequence< uno::Any > aArgument( 1 );
134 uno::Sequence< beans::PropertyValue > aPropValues( mpCfgItem->GetFilterData() );
135 aArgument[ 0 ] <<= aPropValues;
136 mxFilterTracer = xMgr->createInstanceWithArguments( rtl::OUString::createFromAscii( "com.sun.star.util.FilterTracer" ), aArgument );
137 if ( mxFilterTracer.is() )
138 {
139 mxTextSearch = uno::Reference< util::XTextSearch >( mxFilterTracer, uno::UNO_QUERY );
140 mxLogger = uno::Reference< util::logging::XLogger >( mxFilterTracer, uno::UNO_QUERY );
141 if ( mxTextSearch.is() )
142 {
143 maSearchOptions.algorithmType = eSearchAlgorithm;
144 mxTextSearch->setOptions( maSearchOptions );
145 }
146 }
147 }
148 }
149 }
150
~MSFilterTracer()151 MSFilterTracer::~MSFilterTracer()
152 {
153 mxLogger = NULL;
154 mxFilterTracer = NULL;
155 if ( mxHandler.is() )
156 {
157 mxHandler->ignorableWhitespace ( rtl::OUString::createFromAscii( " " ) );
158 mxHandler->endElement( rtl::OUString::createFromAscii( "Document" ) );
159 mxHandler->ignorableWhitespace ( rtl::OUString::createFromAscii( " " ) );
160 mxHandler->endDocument();
161 mxHandler = NULL;
162 }
163 delete mpAttributeList;
164 delete mpCfgItem;
165 delete mpStream;
166 }
167
StartTracing()168 void MSFilterTracer::StartTracing()
169 {
170 mbEnabled = mpCfgItem->ReadBool( rtl::OUString::createFromAscii( "On" ), sal_False );
171 }
172
EndTracing()173 void MSFilterTracer::EndTracing()
174 {
175 mbEnabled = sal_False;
176 }
177
StartElement(const rtl::OUString & rName,uno::Reference<xml::sax::XAttributeList> xAttribs)178 void MSFilterTracer::StartElement( const rtl::OUString& rName, uno::Reference< xml::sax::XAttributeList > xAttribs )
179 {
180 if ( mxHandler.is() )
181 mxHandler->startElement( rName, xAttribs );
182 }
183
EndElement(const rtl::OUString & rName)184 void MSFilterTracer::EndElement( const rtl::OUString& rName )
185 {
186 if ( mxHandler.is() )
187 mxHandler->endElement( rName );
188 }
189
Trace(const rtl::OUString & rElement,const rtl::OUString & rMessage)190 void MSFilterTracer::Trace( const rtl::OUString& rElement, const rtl::OUString& rMessage )
191 {
192 if ( mbEnabled && mxLogger.is() )
193 {
194 sal_Bool bFilter = sal_False;
195 if ( rMessage.getLength() && mxTextSearch.is() )
196 {
197 maSearchOptions.searchString = rMessage;
198 mxTextSearch->setOptions( maSearchOptions );
199 util::SearchResult aSearchResult = mxTextSearch->searchForward( rMessage, 0, rMessage.getLength() );
200 bFilter = aSearchResult.subRegExpressions != 0;
201 }
202 if ( !bFilter )
203 {
204 uno::Reference < xml::sax::XAttributeList > xAttrList( new SvXMLAttributeList( *mpAttributeList ) );
205 if ( mxHandler.is() )
206 mxHandler->startElement( rElement, xAttrList );
207 if ( rMessage.getLength() )
208 {
209 rtl::OUString aEmpty;
210 mxLogger->logp( 0, aEmpty, aEmpty, rMessage );
211 }
212 if ( mxHandler.is() )
213 mxHandler->endElement( rElement );
214 }
215 }
216 }
217
AddAttribute(const::rtl::OUString & sName,const::rtl::OUString & sValue)218 void MSFilterTracer::AddAttribute( const ::rtl::OUString& sName , const ::rtl::OUString& sValue )
219 {
220 if ( mbEnabled )
221 mpAttributeList->AddAttribute( sName, sValue );
222 }
ClearAttributes()223 void MSFilterTracer::ClearAttributes()
224 {
225 if ( mbEnabled )
226 mpAttributeList->Clear();
227 }
228
RemoveAttribute(const::rtl::OUString & sName)229 void MSFilterTracer::RemoveAttribute( const ::rtl::OUString& sName )
230 {
231 if ( mbEnabled )
232 mpAttributeList->RemoveAttribute( sName );
233 }
234
GetProperty(const rtl::OUString & rPropName,const uno::Any * pDefault) const235 uno::Any MSFilterTracer::GetProperty( const rtl::OUString& rPropName, const uno::Any* pDefault ) const
236 {
237 uno::Any aDefault;
238 if ( pDefault )
239 aDefault = *pDefault;
240 return mpCfgItem->ReadAny( rPropName, aDefault );
241 }
242
SetProperty(const::rtl::OUString & rPropName,const uno::Any & rProperty)243 void MSFilterTracer::SetProperty( const ::rtl::OUString& rPropName, const uno::Any& rProperty )
244 {
245 mpCfgItem->WriteAny( rPropName, rProperty );
246 }
247
248