/*******************************************************************************
* Copyright (c) 2011 Wind River Systems, Inc. and others. All rights reserved.
* This program and the accompanying materials are made available under the terms
* of the Eclipse Public License v1.0 which accompanies this distribution, and is
* available at http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Wind River Systems - initial API and implementation
*******************************************************************************/
package org.eclipse.tm.te.tcf.log.core.internal.listener;
import java.io.ByteArrayInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.Platform;
import org.eclipse.osgi.util.NLS;
import org.eclipse.tm.tcf.core.AbstractChannel.TraceListener;
import org.eclipse.tm.tcf.protocol.IChannel;
import org.eclipse.tm.te.tcf.log.core.activator.CoreBundleActivator;
import org.eclipse.tm.te.tcf.log.core.interfaces.IPreferenceKeys;
import org.eclipse.tm.te.tcf.log.core.interfaces.ITracing;
import org.eclipse.tm.te.tcf.log.core.internal.LogManager;
import org.eclipse.tm.te.tcf.log.core.internal.nls.Messages;
/**
* TCF logging channel trace listener implementation.
*/
public class ChannelTraceListener implements TraceListener {
/**
* Time format representing time with milliseconds.
*/
public static final DateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm:ss.SSS"); //$NON-NLS-1$
/**
* Time format representing date and time with milliseconds.
*/
public static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); //$NON-NLS-1$
// Reference to the channel
private final IChannel channel;
/**
* Constructor.
*
* @param channel The channel. Must not be <code>null</code>.
*/
public ChannelTraceListener(IChannel channel) {
Assert.isNotNull(channel);
this.channel = channel;
}
/**
* Return the associated channel.
*
* @return The channel instance.
*/
protected final IChannel getChannel() {
return channel;
}
/* (non-Javadoc)
* @see org.eclipse.tm.tcf.core.AbstractChannel.TraceListener#onChannelClosed(java.lang.Throwable)
*/
@Override
public void onChannelClosed(Throwable error) {
if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITracing.ID_TRACE_CHANNEL_TRACE_LISTENER)) {
CoreBundleActivator.getTraceHandler().trace("TraceListener.onChannelClosed ( " + error + " )", //$NON-NLS-1$ //$NON-NLS-2$
ITracing.ID_TRACE_CHANNEL_TRACE_LISTENER, this);
}
// Get the current time stamp
String date = DATE_FORMAT.format(new Date(System.currentTimeMillis()));
String message = NLS.bind(Messages.ChannelTraceListener_channelClosed_message,
new Object[] {
date,
Integer.toHexString(channel.hashCode()),
error
});
LogManager.getInstance().closeWriter(channel, message);
}
/* (non-Javadoc)
* @see org.eclipse.tm.tcf.core.AbstractChannel.TraceListener#onMessageReceived(char, java.lang.String, java.lang.String, java.lang.String, byte[])
*/
@Override
public void onMessageReceived(char type, String token, String service, String name, byte[] data) {
if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITracing.ID_TRACE_CHANNEL_TRACE_LISTENER)) {
CoreBundleActivator.getTraceHandler().trace("TraceListener.onMessageReceived ( " + type //$NON-NLS-1$
+ ", " + token + ", " + service + ", " + name + ", ... )", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
ITracing.ID_TRACE_CHANNEL_TRACE_LISTENER, this);
}
doLogMessage(type, token, service, name, data, true);
}
/* (non-Javadoc)
* @see org.eclipse.tm.tcf.core.AbstractChannel.TraceListener#onMessageSent(char, java.lang.String, java.lang.String, java.lang.String, byte[])
*/
@Override
public void onMessageSent(final char type, String token, String service, String name, byte[] data) {
if (CoreBundleActivator.getTraceHandler().isSlotEnabled(0, ITracing.ID_TRACE_CHANNEL_TRACE_LISTENER)) {
CoreBundleActivator.getTraceHandler().trace("TraceListener.onMessageSent ( " + type //$NON-NLS-1$
+ ", " + token + ", " + service + ", " + name + ", ... )", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
ITracing.ID_TRACE_CHANNEL_TRACE_LISTENER, this);
}
doLogMessage(type, token, service, name, data, false);
}
/**
* Helper method to output the message to the logger.
*/
private void doLogMessage(final char type, String token, String service, String name, byte[] data, boolean received) {
// Filter out the heart beat messages if not overwritten by the preferences
boolean showHeartbeats = Platform.getPreferencesService().getBoolean(CoreBundleActivator.getUniqueIdentifier(),
IPreferenceKeys.PREF_SHOW_HEARTBEATS, false, null);
if (!showHeartbeats && name != null && name.toLowerCase().contains("heartbeat")) { //$NON-NLS-1$
return;
}
// Format the message
final String message = formatMessage(type, token, service, name, data, received);
// Get the file writer
FileWriter writer = LogManager.getInstance().getWriter(channel);
if (writer != null) {
try {
writer.write(message);
writer.write("\n"); //$NON-NLS-1$
writer.flush();
} catch (IOException e) {
/* ignored on purpose */
}
}
}
/**
* Format the trace message.
*/
protected String formatMessage(char type, String token, String service, String name, byte[] data, boolean received) {
// Get the current time stamp
String time = TIME_FORMAT.format(new Date(System.currentTimeMillis()));
// Decode the arguments again for tracing purpose
String args = null;
if (data != null) {
StringBuilder builder = new StringBuilder();
InputStreamReader reader = new InputStreamReader(new ByteArrayInputStream(data));
try {
int c = reader.read();
while (c != -1) {
builder.append(c != 0 ? Character.valueOf((char)c).charValue() : ' ');
c = reader.read();
}
} catch (IOException ex) { /* ignored on purpose */ }
if (builder.length() > 0) args = builder.toString().trim();
}
// Construct the full message
//
// The message format is: <time>: [<---|--->] <type> <token> <service>#<name> <args>
StringBuilder message = new StringBuilder();
message.append(time).append(":"); //$NON-NLS-1$
message.append(" ").append(received ? "<---" : "--->"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
message.append(" ").append(Character.valueOf(type)); //$NON-NLS-1$
if (token != null) message.append(" ").append(token); //$NON-NLS-1$
if (service != null) message.append(" ").append(service); //$NON-NLS-1$
if (name != null) message.append(" ").append(name); //$NON-NLS-1$
if (args != null && args.trim().length() > 0) message.append(" ").append(args.trim()); //$NON-NLS-1$
return message.toString();
}
}