FELIX-1988 Apply 9.logs_plugin.patch by Valentin Valchev (thanks)

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@911377 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/LogServlet.java b/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/LogServlet.java
index f53dfe6..eb13d7c 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/LogServlet.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/LogServlet.java
@@ -25,10 +25,9 @@
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import org.apache.felix.webconsole.WebConsoleConstants;
+import org.apache.felix.webconsole.SimpleWebConsolePlugin;
 import org.apache.felix.webconsole.WebConsoleUtil;
-import org.apache.felix.webconsole.internal.BaseWebConsolePlugin;
-import org.apache.felix.webconsole.internal.Util;
+import org.apache.felix.webconsole.internal.OsgiManagerPlugin;
 import org.json.JSONException;
 import org.json.JSONWriter;
 import org.osgi.framework.ServiceReference;
@@ -37,31 +36,33 @@
 import org.osgi.service.log.LogService;
 
 
-public class LogServlet extends BaseWebConsolePlugin
+/**
+ * LogServlet provides support for reading the log messages.
+ */
+public class LogServlet extends SimpleWebConsolePlugin implements OsgiManagerPlugin
 {
-    public static final String LABEL = "logs";
-    public static final String TITLE = "Log Service";
+    private static final String LABEL = "logs";
+    private static final String TITLE = "Log Service";
+    private static final String CSS[] = { "/res/ui/logs.css" };
 
     private final static int MAX_LOGS = 200; //maximum number of log entries
 
+    // templates
+    private final String TEMPLATE;
 
+    /** Default constructor */
     public LogServlet()
     {
+        super(LABEL, TITLE, CSS);
+
+        // load templates
+        TEMPLATE = readTemplateFile( "/templates/logs.html" );
     }
 
 
-    public String getLabel()
-    {
-        return LABEL;
-    }
-
-
-    public String getTitle()
-    {
-        return TITLE;
-    }
-
-
+    /**
+     * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
+     */
     protected void doPost( HttpServletRequest req, HttpServletResponse resp ) throws ServletException, IOException
     {
         final int minLevel = WebConsoleUtil.getParameterInt( req, "minLevel", LogService.LOG_DEBUG );
@@ -73,29 +74,19 @@
     }
 
 
-    private void renderJSON( final PrintWriter pw, int minLogLevel ) throws IOException
+    private final void renderJSON( final PrintWriter pw, int minLogLevel ) throws IOException
     {
         // create status line
         final LogReaderService logReaderService = ( LogReaderService ) this.getService( LogReaderService.class
             .getName() );
 
-        StringBuffer statusLine = new StringBuffer();
-        if ( logReaderService == null )
-        {
-            statusLine.append( "Log Service is not installed/running." );
-        }
-        else
-        {
-            statusLine.append( "Log Service is running." );
-        }
-
         JSONWriter jw = new JSONWriter( pw );
         try
         {
             jw.object();
 
             jw.key( "status" );
-            jw.value( statusLine );
+            jw.value( logReaderService == null ? Boolean.FALSE : Boolean.TRUE );
 
             jw.key( "data" );
             jw.array();
@@ -127,6 +118,9 @@
     }
 
 
+    /**
+     * @see org.apache.felix.webconsole.AbstractWebConsolePlugin#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
+     */
     protected void doGet( HttpServletRequest request, HttpServletResponse response ) throws ServletException,
         IOException
     {
@@ -145,23 +139,17 @@
     }
 
 
+    /**
+     * @see org.apache.felix.webconsole.AbstractWebConsolePlugin#renderContent(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
+     */
     protected void renderContent( HttpServletRequest request, HttpServletResponse response ) throws ServletException,
         IOException
     {
-        final PrintWriter pw = response.getWriter();
-
-        final String appRoot = ( String ) request.getAttribute( WebConsoleConstants.ATTR_APP_ROOT );
-        Util.script( pw, appRoot, "logs.js" );
-
-        pw.println( "<div id='plugin_content'/>" );
-
-        Util.startScript( pw );
-        pw.println( "renderLogs( );" );
-        Util.endScript( pw );
+        response.getWriter().print(TEMPLATE);
     }
 
 
-    private void logJson( JSONWriter jw, LogEntry info, int index ) throws JSONException
+    private static final void logJson( JSONWriter jw, LogEntry info, int index ) throws JSONException
     {
         jw.object();
         jw.key( "id" );
@@ -170,6 +158,8 @@
         jw.value( info.getTime() );
         jw.key( "level" );
         jw.value( logLevel( info.getLevel() ) );
+        jw.key( "raw_level" );
+        jw.value( info.getLevel() );
         jw.key( "message" );
         jw.value( info.getMessage() );
         jw.key( "service" );
@@ -180,7 +170,7 @@
     }
 
 
-    private String serviceDescription( ServiceReference serviceReference )
+    private static final String serviceDescription( ServiceReference serviceReference )
     {
         if ( serviceReference == null )
             return "";
@@ -189,7 +179,7 @@
     }
 
 
-    private String logLevel( int level )
+    private static final String logLevel( int level )
     {
         switch ( level )
         {
@@ -206,7 +196,7 @@
     }
 
 
-    private String exceptionMessage( Throwable e )
+    private static final String exceptionMessage( Throwable e )
     {
         if ( e == null )
             return "";
diff --git a/webconsole/src/main/resources/res/ui/logs.css b/webconsole/src/main/resources/res/ui/logs.css
new file mode 100644
index 0000000..a87ad6e
--- /dev/null
+++ b/webconsole/src/main/resources/res/ui/logs.css
@@ -0,0 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#logs, #logs2 {
+	margin: 0;
+	padding: 0
+}
\ No newline at end of file
diff --git a/webconsole/src/main/resources/res/ui/logs.js b/webconsole/src/main/resources/res/ui/logs.js
index 0a3656f..2d6f00f 100644
--- a/webconsole/src/main/resources/res/ui/logs.js
+++ b/webconsole/src/main/resources/res/ui/logs.js
@@ -14,35 +14,26 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-function renderStatusLine() {
-	$("#plugin_content").append( "<div class='fullwidth'><div class='statusline'/></div>" );
-}
-
-function renderView( /* Array of String */ columns, /* String */ buttons ) {
-    renderStatusLine();
-    renderButtons(buttons);
-    var txt = "<div class='table'><table id='plugin_table' class='tablelayout'><thead><tr>";
-    for ( var name in columns ) {
-    	txt = txt + "<th class='col_" + columns[name] + "'>" + columns[name] + "</th>";
-    }
-    txt = txt + "</tr></thead><tbody></tbody></table></div>";
-    $("#plugin_content").append( txt );
-    renderButtons(buttons);
-    renderStatusLine();	
-}
-
-function renderButtons( buttons ) {
-	$("#plugin_content").append( "<form method='post' enctype='multipart/form-data'><div class='fullwidth'><div class='buttons'>" +
-	                             buttons + "</div></div></form>" );
-}
-
+ 
+var logsElem  = false;
+var logs2Elem = false;
+var tableElem = false;
+var statElem  = false;
+ 
 function renderData( eventData )  {
-	$(".statusline").empty().append(eventData.status);
-	$("#plugin_table > tbody > tr").remove();	
-    for ( var idx in eventData.data ) {
-        entry( eventData.data[idx] );
-    }
-    $("#plugin_table").trigger("update");
+	statElem.empty().append(eventData.status ? i18n.status_ok : i18n.status_missing);
+	logsElem.css("display", eventData.status ? "block" : "none"  );
+	if (eventData.status) {
+		$("#plugin_table > tbody > tr").remove();	
+		var hasEntries = false;
+		for ( var idx in eventData.data ) {
+			entry( eventData.data[idx] );
+			hasEntries = true;
+		}
+		logs2Elem.css("display", hasEntries ? "block" : "none"  );
+	
+		if (hasEntries) tableElem.trigger("update").trigger("applyWidgets");
+	}
 }
 
 function entry( /* Object */ dataEntry ) {
@@ -57,11 +48,16 @@
     var level = dataEntry.level;
     var exception = dataEntry.exception;
     var service = dataEntry.service;
-
+	switch (dataEntry.raw_level) { // i18n
+		case 1: level = i18n.error; break;
+		case 2: level = i18n.warn; break;
+		case 3: level = i18n.info; break;
+		case 4: level = i18n.debug; break;
+	}
     parent.appendChild( td( null, null, [ text( printDate(dataEntry.received) ) ] ) );
     parent.appendChild( td( null, null, [ text( level ) ] ) );    
-    parent.appendChild( td( null, null, [ text( message ) ] ) );
-    parent.appendChild( td( null, null, [ text( service ) ] ) );
+    parent.appendChild( td( null, null, [ text( wordWrap(message) ) ] ) );
+    parent.appendChild( td( null, null, [ text( wordWrap(service) ) ] ) );
     parent.appendChild( td( null, null, [ text( exception ) ] ) );
 }
 
@@ -72,25 +68,24 @@
 }
 
 function loadData() {
-	$.get(pluginRoot + "/data.json", { "minLevel":$("#minLevel").val()}, function(data) {
-	    renderData(data);
-	}, "json");	
+	$.get(pluginRoot + "/data.json", { "minLevel":$(".minLevel").val()}, renderData, "json");
+	return false; // for button
 }
 
-function renderLogs() {
-	$(document).ready(function(){
-	    renderView( ["Received", "Level", "Message", "Service", "Exception"],
-	    		 "<span>Severity at least: <select id='minLevel'><option value='1'>ERROR</option>" + 
-	    		 "<option value='2'>WARN</option><option value='3'>INFO</option><option value='4' selected='selected'>DEBUG</option></select></span> "+
-	    		 "<button class='reloadButton' type='button' name='reload'>Reload</button>");
-	    loadData();
-	    
-	    $("#plugin_table").tablesorter();
-	    $(".reloadButton").click(loadData);
-	    $("#minLevel").change(function() {
-	    	$.post(pluginRoot, { "minLevel":$("#minLevel").val()}, function(data) {
-	    	    renderData(data);
-	    	}, "json");
-	    });
-	});
-}
\ No newline at end of file
+$(document).ready(function() {
+	// install user interaction handlers
+    $(".reloadButton").click(loadData);
+    $(".minLevel").change(function() {
+		var value = $(this).val();
+		$(".minLevel").val(value); // same values for both select boxes
+    	$.post(pluginRoot, {"minLevel":value}, function(data) {
+    	    renderData(data);
+    	}, "json");
+    });
+	logsElem  = $("#logs");
+    logs2Elem = $("#logs2");
+	tableElem = $("#plugin_table");
+	statElem  = $(".statline");
+	// load logs
+	loadData();
+});
\ No newline at end of file
diff --git a/webconsole/src/main/resources/templates/logs.html b/webconsole/src/main/resources/templates/logs.html
new file mode 100644
index 0000000..17aba1a
--- /dev/null
+++ b/webconsole/src/main/resources/templates/logs.html
@@ -0,0 +1,68 @@
+<script type="text/javascript" src="res/ui/logs.js"></script>
+<script type="text/javascript">
+// <![CDATA[
+// i18n
+var i18n = {
+	status_ok      : "${log.status.ok}",
+	status_missing : "${log.status.missing}",
+	error : "${log.level.error}",
+	warn  : "${log.level.warn}",
+	info  : "${log.level.info}",
+	debug : "${log.level.debug}"
+}
+// ]]>
+</script>
+
+<!-- status line -->
+<p class="statline">&nbsp;</p>
+
+<div id="logs">
+<!-- buttons top -->
+<form method="post" enctype="multipart/form-data" action="">
+	<div class="ui-widget-header ui-corner-top buttonGroup">
+		<label>${log.severity.label}</label>
+		<select class="minLevel">
+			<option value="1">${log.level.error}</option>
+			<option value="2">${log.level.warn}</option>
+			<option value="3">${log.level.info}</option>
+			<option value="4" selected="selected">${log.level.debug}</option>
+		</select>
+		<button class="reloadButton">${reload}</button>
+	</div>
+</form>
+
+<div id="logs2">
+<table id="plugin_table" class="tablesorter nicetable">
+	<thead>
+		<tr>
+			<th class="col_Received">${log.received}</th>
+			<th class="col_Level">${log.level}</th>
+			<th class="col_Message">${log.message}</th>
+			<th class="col_Service">${log.service}</th>
+			<th class="col_Exception">${log.exception}</th>
+		</tr>
+	</thead>
+	<tbody>
+		<tr><td colspan="5">&nbsp;</td></tr>
+	</tbody>
+</table>
+
+<!-- buttons bottom -->
+<form method="post" enctype="multipart/form-data" action="">
+	<div class="ui-widget-header ui-corner-bottom buttonGroup">
+		<label>${log.severity.label}</label>
+		<select class="minLevel">
+			<option value="1">${log.level.error}</option>
+			<option value="2">${log.level.warn}</option>
+			<option value="3">${log.level.info}</option>
+			<option value="4" selected="selected">${log.level.debug}</option>
+		</select>
+		<button class="reloadButton">${reload}</button>
+	</div>
+</form>
+</div> <!-- logs2 -->
+
+</div> <!-- logs -->
+
+<!-- status line -->
+<p class="statline">&nbsp;</p>