1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_desktop.hxx"
30 
31 #include "dp_misc.h"
32 #include "rtl/strbuf.hxx"
33 #include "osl/time.h"
34 #include "osl/thread.h"
35 #include "cppuhelper/compbase1.hxx"
36 #include "comphelper/anytostring.hxx"
37 #include "comphelper/servicedecl.hxx"
38 #include "comphelper/unwrapargs.hxx"
39 #include "com/sun/star/deployment/DeploymentException.hpp"
40 #include "com/sun/star/ucb/XProgressHandler.hpp"
41 #include "com/sun/star/ucb/XSimpleFileAccess.hpp"
42 #include "com/sun/star/io/XSeekable.hpp"
43 #include <stdio.h>
44 
45 
46 using namespace ::rtl;
47 using namespace ::com::sun::star;
48 using namespace ::com::sun::star::uno;
49 
50 namespace dp_log {
51 
52 typedef ::cppu::WeakComponentImplHelper1<ucb::XProgressHandler> t_log_helper;
53 
54 //==============================================================================
55 class ProgressLogImpl : public ::dp_misc::MutexHolder, public t_log_helper
56 {
57     Reference<io::XOutputStream> m_xLogFile;
58     sal_Int32 m_log_level;
59     void log_write( OString const & text );
60 
61 protected:
62     virtual void SAL_CALL disposing();
63     virtual ~ProgressLogImpl();
64 
65 public:
66     ProgressLogImpl( Sequence<Any> const & args,
67                      Reference<XComponentContext> const & xContext );
68 
69     // XProgressHandler
70     virtual void SAL_CALL push( Any const & Status ) throw (RuntimeException);
71     virtual void SAL_CALL update( Any const & Status ) throw (RuntimeException);
72     virtual void SAL_CALL pop() throw (RuntimeException);
73 };
74 
75 //______________________________________________________________________________
76 ProgressLogImpl::~ProgressLogImpl()
77 {
78 }
79 
80 //______________________________________________________________________________
81 void ProgressLogImpl::disposing()
82 {
83     try {
84         if (m_xLogFile.is()) {
85             m_xLogFile->closeOutput();
86             m_xLogFile.clear();
87         }
88     }
89     catch (Exception & exc) {
90         (void) exc;
91         OSL_ENSURE( 0, OUStringToOString(
92                         exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() );
93     }
94 }
95 
96 //______________________________________________________________________________
97 ProgressLogImpl::ProgressLogImpl(
98     Sequence<Any> const & args,
99     Reference<XComponentContext> const & xContext )
100     : t_log_helper( getMutex() ),
101       m_log_level( 0 )
102 {
103     OUString log_file;
104     boost::optional< Reference<task::XInteractionHandler> > interactionHandler;
105     comphelper::unwrapArgs( args, log_file, interactionHandler );
106 
107     Reference<ucb::XSimpleFileAccess> xSimpleFileAccess(
108         xContext->getServiceManager()->createInstanceWithContext(
109             OUSTR("com.sun.star.ucb.SimpleFileAccess"),
110             xContext ), UNO_QUERY_THROW );
111     // optional ia handler:
112     if (interactionHandler)
113         xSimpleFileAccess->setInteractionHandler( *interactionHandler );
114 
115     m_xLogFile.set(
116         xSimpleFileAccess->openFileWrite( log_file ), UNO_QUERY_THROW );
117     Reference<io::XSeekable> xSeekable( m_xLogFile, UNO_QUERY_THROW );
118     xSeekable->seek( xSeekable->getLength() );
119 
120     // write log stamp
121     OStringBuffer buf;
122     buf.append(
123         RTL_CONSTASCII_STRINGPARAM("###### Progress log entry ") );
124     TimeValue m_start_time, tLocal;
125     oslDateTime date_time;
126     if (osl_getSystemTime( &m_start_time ) &&
127         osl_getLocalTimeFromSystemTime( &m_start_time, &tLocal ) &&
128         osl_getDateTimeFromTimeValue( &tLocal, &date_time ))
129     {
130         char ar[ 128 ];
131         snprintf(
132             ar, sizeof (ar),
133             "%04d-%02d-%02d %02d:%02d:%02d ",
134             date_time.Year, date_time.Month, date_time.Day,
135             date_time.Hours, date_time.Minutes, date_time.Seconds );
136         buf.append( ar );
137     }
138     buf.append( RTL_CONSTASCII_STRINGPARAM("######\n") );
139     log_write( buf.makeStringAndClear() );
140 }
141 
142 //______________________________________________________________________________
143 void ProgressLogImpl::log_write( OString const & text )
144 {
145     try {
146         if (m_xLogFile.is()) {
147             m_xLogFile->writeBytes(
148                 Sequence< sal_Int8 >(
149                     reinterpret_cast< sal_Int8 const * >(text.getStr()),
150                     text.getLength() ) );
151         }
152     }
153     catch (io::IOException & exc) {
154         (void) exc;
155         OSL_ENSURE( 0, OUStringToOString(
156                         exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() );
157     }
158 }
159 
160 // XProgressHandler
161 //______________________________________________________________________________
162 void ProgressLogImpl::push( Any const & Status )
163     throw (RuntimeException)
164 {
165     update( Status );
166     OSL_ASSERT( m_log_level >= 0 );
167     ++m_log_level;
168 }
169 
170 //______________________________________________________________________________
171 void ProgressLogImpl::update( Any const & Status )
172     throw (RuntimeException)
173 {
174     if (! Status.hasValue())
175         return;
176 
177     OUStringBuffer buf;
178     OSL_ASSERT( m_log_level >= 0 );
179     for ( sal_Int32 n = 0; n < m_log_level; ++n )
180         buf.append( static_cast<sal_Unicode>(' ') );
181 
182     OUString msg;
183     if (Status >>= msg) {
184         buf.append( msg );
185     }
186     else {
187         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("ERROR: ") );
188         buf.append( ::comphelper::anyToString(Status) );
189     }
190     buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\n") );
191     log_write( OUStringToOString(
192                    buf.makeStringAndClear(), osl_getThreadTextEncoding() ) );
193 }
194 
195 //______________________________________________________________________________
196 void ProgressLogImpl::pop() throw (RuntimeException)
197 {
198     OSL_ASSERT( m_log_level > 0 );
199     --m_log_level;
200 }
201 
202 namespace sdecl = comphelper::service_decl;
203 sdecl::class_<ProgressLogImpl, sdecl::with_args<true> > servicePLI;
204 extern sdecl::ServiceDecl const serviceDecl(
205     servicePLI,
206     // a private one:
207     "com.sun.star.comp.deployment.ProgressLog",
208     "com.sun.star.comp.deployment.ProgressLog" );
209 
210 } // namespace dp_log
211 
212