001/*
002 * Copyright (c) 2004-2010 The Regents of the University of California.
003 * All rights reserved.
004 *
005 * '$Author: jianwu $'
006 * '$Date: 2013-04-30 20:53:16 +0000 (Tue, 30 Apr 2013) $' 
007 * '$Revision: 31973 $'
008 * 
009 * Permission is hereby granted, without written agreement and without
010 * license or royalty fees, to use, copy, modify, and distribute this
011 * software and its documentation for any purpose, provided that the above
012 * copyright notice and the following two paragraphs appear in all copies
013 * of this software.
014 *
015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
019 * SUCH DAMAGE.
020 *
021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
026 * ENHANCEMENTS, OR MODIFICATIONS.
027 *
028 */
029
030package org.kepler.actor;
031
032import java.io.File;
033import java.io.IOException;
034
035import org.apache.commons.logging.Log;
036import org.apache.commons.logging.LogFactory;
037import org.kepler.io.SharedLog;
038
039import ptolemy.actor.TypedAtomicActor;
040import ptolemy.actor.TypedIOPort;
041import ptolemy.data.BooleanToken;
042import ptolemy.data.StringToken;
043import ptolemy.data.expr.FileParameter;
044import ptolemy.data.expr.Parameter;
045import ptolemy.data.expr.StringParameter;
046import ptolemy.data.type.BaseType;
047import ptolemy.kernel.CompositeEntity;
048import ptolemy.kernel.util.IllegalActionException;
049import ptolemy.kernel.util.NameDuplicationException;
050
051//////////////////////////////////////////////////////////////////////////
052//// Logger
053
054/**
055 * Log information directed into a file. All Logger actors can write into the
056 * same file, if their parameter points to the same file. Format as it is, or
057 * XML. text format: date: header: text XML format:
058 * 
059 * 
060 * If the text is empty (or only white spaces), nothing will be written. So you
061 * do not need to filter out e.g. empty stderr messages before connecting to
062 * this Logger actor.
063 * 
064 * @author Norbert Podhorszki
065 * @version $Id: Logger.java 31973 2013-04-30 20:53:16Z jianwu $
066 * @since Ptolemy II 5.0.1
067 */
068public class Logger extends TypedAtomicActor {
069        /**
070         * Construct an actor with the given container and name.
071         * 
072         * @param container
073         *            The container.
074         * @param name
075         *            The name of this actor.
076         * @exception IllegalActionException
077         *                If the actor cannot be contained by the proposed
078         *                container.
079         * @exception NameDuplicationException
080         *                If the container already has an actor with this name.
081         */
082        public Logger(CompositeEntity container, String name)
083                        throws NameDuplicationException, IllegalActionException {
084                super(container, name);
085
086                // Logger file parameter
087                logfile = new FileParameter(this, "logfile");
088                logfile.setExpression("$CWD" + File.separator + "kepler.log");
089
090                // Uncomment the next line to see debugging statements
091                // addDebugListener(new ptolemy.kernel.util.StreamListener());
092                text = new TypedIOPort(this, "text", true, false);
093                text.setTypeEquals(BaseType.STRING);
094                new Parameter(text, "_showName", BooleanToken.FALSE);
095
096                // header is a fixed string to print out (e.g. an actor name)
097                header = new StringParameter(this, "header");
098                header.setExpression("");
099
100                // parameter for format: "text" or "xml"
101                format = new StringParameter(this, "format");
102                format.setExpression("text");
103                
104                // parameter for append:
105                append = new Parameter(this,
106                                "alwaysAppend");
107                append.setTypeEquals(BaseType.BOOLEAN);
108                append.setToken(BooleanToken.FALSE);
109        }
110
111        /***********************************************************
112         * ports and parameters
113         */
114
115        /**
116         * The log file. It can be changed between firings. The file will be created
117         * if does not exists, otherwise text will be appended to the existing file.
118         */
119        public FileParameter logfile;
120
121        /**
122         * The text to be printed into the log. This port is expects strings.
123         */
124        public TypedIOPort text;
125
126        /**
127         * The header information to be printed with the log. Useful to provide an
128         * actor name, or some meaningful name. Date is printed independently to the
129         * log.
130         */
131        public StringParameter header;
132
133        /**
134         * The format of the logger. Currently "text" or "xml". Other value will
135         * mean "text". If different loggers use different format option for the
136         * same file, the output will be a mixture of different formats.
137         */
138        public StringParameter format;
139        
140        /**
141         * If true, always append the new log info to the log file.
142         */
143        public Parameter append;
144
145        /***********************************************************
146         * public methods
147         */
148
149        /**
150         * Set the format for the logging.
151         */
152        public void initialize() throws IllegalActionException {
153                super.initialize();
154                String logFormat = format.stringValue();
155                _xmlFormat = logFormat.trim().equalsIgnoreCase("xml");
156                _header = header.stringValue();
157                _sharedLog = new SharedLog(_xmlFormat);
158                _append = ((BooleanToken)append.getToken()).booleanValue();
159                if (isDebugging)
160                        log.debug("format is [" + logFormat + "]. header is [" + _header
161                                        + "].");
162
163        }
164
165        /**
166         * fire
167         * 
168         * @exception IllegalActionException
169         *                Not thrown.
170         */
171        public void fire() throws IllegalActionException {
172                super.fire();
173
174                String logText = ((StringToken) text.get(0)).stringValue();
175
176                _sharedLog.print(logfile.asFile(), _header, logText, _append);
177        }
178
179        /**
180         * Close all opened log files. This method is invoked exactly once per
181         * execution of an application. None of the other action methods should be
182         * be invoked after it.
183         * 
184         * @exception IllegalActionException
185         *                Not thrown in this base class.
186         */
187        public void wrapup() throws IllegalActionException {
188                super.wrapup();
189                if (isDebugging)
190                        log.debug("wrapup begin");
191                try {
192                        _sharedLog.closeAll();
193                } catch (IOException ex) {
194                        log.error("Error at wrapup: " + ex);
195                }
196                if (isDebugging)
197                        log.debug("wrapup end");
198        }
199
200        /**
201         * Close all opened log files. This method is invoked exactly once per
202         * execution of an application. None of the other action methods should be
203         * be invoked after it.
204         * 
205         * @exception IllegalActionException
206         *                Not thrown in this base class.
207         */
208        public void stop() {
209                if (isDebugging)
210                        log.debug("stop begin");
211                super.stop();
212                try {
213                        _sharedLog.closeAll();
214                } catch (IOException ex) {
215                        log.error("Error at stop: " + ex);
216                }
217                if (isDebugging)
218                        log.debug("stop end");
219        }
220
221        private boolean _xmlFormat = false;
222        private String _header;
223        private SharedLog _sharedLog;
224        private boolean _append = false;
225
226        // apache commons log for the source code logging.
227        private static final Log log = LogFactory.getLog(Logger.class.getName());
228        private static final boolean isDebugging = log.isDebugEnabled();
229
230}