// ========================================================================
// Copyright (c) 2006-2011 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.osgi.equinoxtools.console;
import java.util.LinkedList;
import java.util.Queue;
import org.eclipse.jetty.osgi.equinoxtools.console.WebConsoleWriterOutputStream.OnFlushListener;
/**
* Processing of the messages to be received and sent to the chat servlets.
* Made to be extended for filtering of the messages and commands.
*/
public class EquinoxChattingSupport
{
private WebConsoleSession _consoleSession;
public EquinoxChattingSupport(WebConsoleSession consoleSession)
{
_consoleSession = consoleSession;
}
/**
* Split the output into multiple lines.
* Format them for the json messages sent to the chat.
* Empties the console output from what is already displayed in the chat.
* @return The lines to add to the message queue of each client.
*/
protected Queue<String> processConsoleOutput(boolean escape, OnFlushListener onflush)
{
Queue<String> result = new LinkedList<String>();
String toDisplay = _consoleSession.getOutputAsWriter().getBuffer().toString();
//the last listener to be called is in charge of clearing the console.
boolean clearConsole = _consoleSession.getOnFlushListeners().indexOf(onflush) == _consoleSession.getOnFlushListeners().size();
if (clearConsole)
{
_consoleSession.clearOutput();
}
boolean lastLineIsComplete = toDisplay.endsWith("\n") || toDisplay.endsWith("\r");
String[] lines = toDisplay.split("\n");
String lastLine = lastLineIsComplete ? null : lines[lines.length-1];
if (clearConsole)
{
_consoleSession.getOutputAsWriter().append(lastLine);
}
for (int lnNb = 0; lnNb < (lastLineIsComplete ? lines.length : lines.length-1); lnNb++)
{
String line = lines[lnNb];
while (line.trim().startsWith("null"))
{//hum..
line = line.trim().substring("null".length()).trim();
}
if (line.startsWith("osgi>"))
{
result.add("osgi>");
result.add(escape ? jsonEscapeString(line.substring("osgi>".length())) : line.substring("osgi>".length()));
}
else
{
result.add("
");
result.add(escape ? jsonEscapeString(line) : line);
}
}
return result;
}
/**
* http://www.ietf.org/rfc/rfc4627.txt
* @param str
* @return The same string escaped according to the JSON RFC.
*/
public static String jsonEscapeString(String str)
{
StringBuilder sb = new StringBuilder();
char[] asChars = str.toCharArray();
for (char ch : asChars)
{
switch (ch)
{
//the reserved characters
case '"':
sb.append("\\\"");
break;
case '\\':
sb.append("\\\\");
break;
case '\b':
sb.append("\\b");
break;
case '\f':
sb.append("\\f");
break;
case '\n':
sb.append("\\n");
break;
case '\r':
sb.append("\\r");
break;
case '\t':
sb.append("\\t");
break;
case '/':
sb.append("\\/");
break;
default:
//The non reserved characters
if (ch >= '\u0000' && ch <= '\u001F')
{
//escape as a unicode number when out of range.
String ss = Integer.toHexString(ch);
sb.append("\\u");
for (int i = 0; i < 4 - ss.length(); i++)
{
//padding
sb.append('0');
}
sb.append(ss.toUpperCase());
}
else
{
sb.append(ch);
}
}
}
return sb.toString();
}
public void broadcast(OnFlushListener source)
{
for (OnFlushListener onflush : _consoleSession.getOnFlushListeners())
{
if (onflush != source)
{
onflush.onFlush();
}
}
}
}