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_desktop.hxx"
26 
27 #include "dp_misc.h"
28 #include "rtl/strbuf.hxx"
29 #include "osl/time.h"
30 #include "osl/thread.h"
31 #include "cppuhelper/compbase1.hxx"
32 #include "comphelper/anytostring.hxx"
33 #include "comphelper/servicedecl.hxx"
34 #include "comphelper/unwrapargs.hxx"
35 #include "com/sun/star/deployment/DeploymentException.hpp"
36 #include "com/sun/star/ucb/XProgressHandler.hpp"
37 #include "com/sun/star/ucb/XSimpleFileAccess.hpp"
38 #include "com/sun/star/io/XSeekable.hpp"
39 #include <stdio.h>
40 
41 
42 using namespace ::rtl;
43 using namespace ::com::sun::star;
44 using namespace ::com::sun::star::uno;
45 
46 namespace dp_log {
47 
48 typedef ::cppu::WeakComponentImplHelper1<ucb::XProgressHandler> t_log_helper;
49 
50 //==============================================================================
51 class ProgressLogImpl : public ::dp_misc::MutexHolder, public t_log_helper
52 {
53     Reference<io::XOutputStream> m_xLogFile;
54     sal_Int32 m_log_level;
55     void log_write( OString const & text );
56 
57 protected:
58     virtual void SAL_CALL disposing();
59     virtual ~ProgressLogImpl();
60 
61 public:
62     ProgressLogImpl( Sequence<Any> const & args,
63                      Reference<XComponentContext> const & xContext );
64 
65     // XProgressHandler
66     virtual void SAL_CALL push( Any const & Status ) throw (RuntimeException);
67     virtual void SAL_CALL update( Any const & Status ) throw (RuntimeException);
68     virtual void SAL_CALL pop() throw (RuntimeException);
69 };
70 
71 //______________________________________________________________________________
~ProgressLogImpl()72 ProgressLogImpl::~ProgressLogImpl()
73 {
74 }
75 
76 //______________________________________________________________________________
disposing()77 void ProgressLogImpl::disposing()
78 {
79     try {
80         if (m_xLogFile.is()) {
81             m_xLogFile->closeOutput();
82             m_xLogFile.clear();
83         }
84     }
85     catch (Exception & exc) {
86         (void) exc;
87         OSL_ENSURE( 0, OUStringToOString(
88                         exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() );
89     }
90 }
91 
92 //______________________________________________________________________________
ProgressLogImpl(Sequence<Any> const & args,Reference<XComponentContext> const & xContext)93 ProgressLogImpl::ProgressLogImpl(
94     Sequence<Any> const & args,
95     Reference<XComponentContext> const & xContext )
96     : t_log_helper( getMutex() ),
97       m_log_level( 0 )
98 {
99     OUString log_file;
100     boost::optional< Reference<task::XInteractionHandler> > interactionHandler;
101     comphelper::unwrapArgs( args, log_file, interactionHandler );
102 
103     Reference<ucb::XSimpleFileAccess> xSimpleFileAccess(
104         xContext->getServiceManager()->createInstanceWithContext(
105             OUSTR("com.sun.star.ucb.SimpleFileAccess"),
106             xContext ), UNO_QUERY_THROW );
107     // optional ia handler:
108     if (interactionHandler)
109         xSimpleFileAccess->setInteractionHandler( *interactionHandler );
110 
111     m_xLogFile.set(
112         xSimpleFileAccess->openFileWrite( log_file ), UNO_QUERY_THROW );
113     Reference<io::XSeekable> xSeekable( m_xLogFile, UNO_QUERY_THROW );
114     xSeekable->seek( xSeekable->getLength() );
115 
116     // write log stamp
117     OStringBuffer buf;
118     buf.append(
119         RTL_CONSTASCII_STRINGPARAM("###### Progress log entry ") );
120     TimeValue m_start_time, tLocal;
121     oslDateTime date_time;
122     if (osl_getSystemTime( &m_start_time ) &&
123         osl_getLocalTimeFromSystemTime( &m_start_time, &tLocal ) &&
124         osl_getDateTimeFromTimeValue( &tLocal, &date_time ))
125     {
126         char ar[ 128 ];
127         snprintf(
128             ar, sizeof (ar),
129             "%04d-%02d-%02d %02d:%02d:%02d ",
130             date_time.Year, date_time.Month, date_time.Day,
131             date_time.Hours, date_time.Minutes, date_time.Seconds );
132         buf.append( ar );
133     }
134     buf.append( RTL_CONSTASCII_STRINGPARAM("######\n") );
135     log_write( buf.makeStringAndClear() );
136 }
137 
138 //______________________________________________________________________________
log_write(OString const & text)139 void ProgressLogImpl::log_write( OString const & text )
140 {
141     try {
142         if (m_xLogFile.is()) {
143             m_xLogFile->writeBytes(
144                 Sequence< sal_Int8 >(
145                     reinterpret_cast< sal_Int8 const * >(text.getStr()),
146                     text.getLength() ) );
147         }
148     }
149     catch (io::IOException & exc) {
150         (void) exc;
151         OSL_ENSURE( 0, OUStringToOString(
152                         exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() );
153     }
154 }
155 
156 // XProgressHandler
157 //______________________________________________________________________________
push(Any const & Status)158 void ProgressLogImpl::push( Any const & Status )
159     throw (RuntimeException)
160 {
161     update( Status );
162     OSL_ASSERT( m_log_level >= 0 );
163     ++m_log_level;
164 }
165 
166 //______________________________________________________________________________
update(Any const & Status)167 void ProgressLogImpl::update( Any const & Status )
168     throw (RuntimeException)
169 {
170     if (! Status.hasValue())
171         return;
172 
173     OUStringBuffer buf;
174     OSL_ASSERT( m_log_level >= 0 );
175     for ( sal_Int32 n = 0; n < m_log_level; ++n )
176         buf.append( static_cast<sal_Unicode>(' ') );
177 
178     OUString msg;
179     if (Status >>= msg) {
180         buf.append( msg );
181     }
182     else {
183         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("ERROR: ") );
184         buf.append( ::comphelper::anyToString(Status) );
185     }
186     buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\n") );
187     log_write( OUStringToOString(
188                    buf.makeStringAndClear(), osl_getThreadTextEncoding() ) );
189 }
190 
191 //______________________________________________________________________________
pop()192 void ProgressLogImpl::pop() throw (RuntimeException)
193 {
194     OSL_ASSERT( m_log_level > 0 );
195     --m_log_level;
196 }
197 
198 namespace sdecl = comphelper::service_decl;
199 sdecl::class_<ProgressLogImpl, sdecl::with_args<true> > servicePLI;
200 extern sdecl::ServiceDecl const serviceDecl(
201     servicePLI,
202     // a private one:
203     "com.sun.star.comp.deployment.ProgressLog",
204     "com.sun.star.comp.deployment.ProgressLog" );
205 
206 } // namespace dp_log
207 
208