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