FELIX-1988 Apply 13.components_plugin.patch by Valentin Valchev (thanks)
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@911450 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/ComponentsServlet.java b/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/ComponentsServlet.java
index f6ef5c4..ce38ab4 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/ComponentsServlet.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/ComponentsServlet.java
@@ -19,6 +19,7 @@
import java.io.IOException;
import java.io.PrintWriter;
+import java.io.StringWriter;
import java.util.Arrays;
import java.util.Collections;
import java.util.Dictionary;
@@ -33,10 +34,15 @@
import org.apache.felix.scr.Component;
import org.apache.felix.scr.Reference;
import org.apache.felix.scr.ScrService;
+import org.apache.felix.webconsole.ConfigurationPrinter;
+import org.apache.felix.webconsole.DefaultVariableResolver;
+import org.apache.felix.webconsole.SimpleWebConsolePlugin;
import org.apache.felix.webconsole.WebConsoleConstants;
import org.apache.felix.webconsole.WebConsoleUtil;
import org.apache.felix.webconsole.internal.BaseWebConsolePlugin;
+import org.apache.felix.webconsole.internal.OsgiManagerPlugin;
import org.apache.felix.webconsole.internal.Util;
+import org.apache.felix.webconsole.internal.core.BundlesServlet;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONWriter;
@@ -51,43 +57,46 @@
import org.osgi.service.metatype.MetaTypeService;
-public class ComponentsServlet extends BaseWebConsolePlugin
+/**
+ * ComponentsServlet provides a plugin for managing Service Components Runtime.
+ */
+public class ComponentsServlet extends SimpleWebConsolePlugin implements OsgiManagerPlugin
{
private static final long serialVersionUID = 1L;
- public static final String NAME = "components";
+ private static final String LABEL = "components";
+ private static final String TITLE = "Components";
+ private static final String CSS[] = { "/res/ui/bundles.css" }; // yes, it's correct!
- public static final String LABEL = "Components";
+ // actions
+ private static final String OPERATION = "action";
+ private static final String OPERATION_ENABLE = "enable";
+ private static final String OPERATION_DISABLE = "disable";
+ private static final String OPERATION_CONFIGURE = "configure";
- public static final String COMPONENT_ID = "componentId";
-
- public static final String OPERATION = "action";
-
- public static final String OPERATION_ENABLE = "enable";
-
- public static final String OPERATION_DISABLE = "disable";
-
- public static final String OPERATION_CONFIGURE = "configure";
-
+ // needed services
private static final String SCR_SERVICE = ScrService.class.getName();
-
private static final String META_TYPE_NAME = MetaTypeService.class.getName();
-
private static final String CONFIGURATION_ADMIN_NAME = ConfigurationAdmin.class.getName();
- public String getTitle()
+ // templates
+ private final String TEMPLATE;
+
+ /** Default constructor */
+ public ComponentsServlet()
{
- return LABEL;
+ super(LABEL, TITLE, CSS);
+
+ // load templates
+ TEMPLATE = readTemplateFile( "/templates/components.html" );
}
- public String getLabel()
- {
- return NAME;
- }
-
+ /**
+ * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
+ */
protected void doPost( HttpServletRequest request, HttpServletResponse response ) throws IOException
{
final RequestInfo reqInfo = new RequestInfo(request);
@@ -116,6 +125,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 {
final RequestInfo reqInfo = new RequestInfo(request);
@@ -136,27 +148,25 @@
super.doGet( request, response );
}
+ /**
+ * @see org.apache.felix.webconsole.AbstractWebConsolePlugin#renderContent(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
+ */
protected void renderContent( HttpServletRequest request, HttpServletResponse response ) throws IOException
{
// get request info from request attribute
final RequestInfo reqInfo = getRequestInfo(request);
- final PrintWriter pw = response.getWriter();
- final String appRoot = ( String ) request.getAttribute( WebConsoleConstants.ATTR_APP_ROOT );
+ StringWriter w = new StringWriter();
+ PrintWriter w2 = new PrintWriter(w);
+ renderResult( w2, reqInfo.component );
+
+ // prepare variables
+ DefaultVariableResolver vars = ( ( DefaultVariableResolver ) WebConsoleUtil.getVariableResolver( request ) );
+ vars.put( "__drawDetails__", reqInfo.componentRequested ? Boolean.TRUE : Boolean.FALSE );
+ vars.put( "__data__", w.toString() );
- Util.startScript( pw );
- pw.println( "var imgRoot = '" + appRoot + "/res/imgs';");
- pw.println( "var drawDetails = " + reqInfo.componentRequested + ";");
- Util.endScript( pw );
-
- Util.script(pw, appRoot, "components.js");
-
- pw.println( "<div id='plugin_content'/>");
- Util.startScript( pw );
- pw.print( "renderComponents(");
- renderResult( pw, reqInfo.component );
- pw.println(");" );
- Util.endScript( pw );
+ response.getWriter().print( TEMPLATE );
+
}
@@ -172,7 +182,7 @@
if ( scrService == null )
{
jw.key( "status" );
- jw.value( "Apache Felix Declarative Service required for this function" );
+ jw.value( -1 );
}
else
{
@@ -181,7 +191,7 @@
if ( components == null || components.length == 0 )
{
jw.key( "status" );
- jw.value( "No components installed currently" );
+ jw.value( 0 );
}
else
{
@@ -201,7 +211,7 @@
}
buffer.append(" installed.");
jw.key("status");
- jw.value(buffer.toString());
+ jw.value(componentMap.size());
// render components
jw.key( "data" );
@@ -479,17 +489,17 @@
return false;
}
- protected ConfigurationAdmin getConfigurationAdmin()
+ private final ConfigurationAdmin getConfigurationAdmin()
{
return ( ConfigurationAdmin ) getService( CONFIGURATION_ADMIN_NAME );
}
- private ScrService getScrService()
+ final ScrService getScrService()
{
return ( ScrService ) getService( SCR_SERVICE );
}
- protected MetaTypeService getMetaTypeService()
+ private final MetaTypeService getMetaTypeService()
{
return ( MetaTypeService ) getService( META_TYPE_NAME );
}
@@ -556,7 +566,7 @@
}
- public static RequestInfo getRequestInfo(final HttpServletRequest request)
+ static RequestInfo getRequestInfo(final HttpServletRequest request)
{
return (RequestInfo)request.getAttribute(ComponentsServlet.class.getName());
}
diff --git a/webconsole/src/main/resources/res/ui/components.js b/webconsole/src/main/resources/res/ui/components.js
index 6728e04..9b2ba33 100644
--- a/webconsole/src/main/resources/res/ui/components.js
+++ b/webconsole/src/main/resources/res/ui/components.js
@@ -6,7 +6,7 @@
* (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
+ * 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,
@@ -14,43 +14,33 @@
* 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, /* Array of 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>" );
-}
-
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");
- if ( drawDetails ) {
- renderDetails(eventData);
- }
+ switch(eventData.status) {
+ case -1: // no event admin
+ $(".statline").html(i18n.stat_no_service);
+ $("#scr").addClass('ui-helper-hidden');
+ break;
+ case 0: // no components
+ $(".statline").html(i18n.stat_no_components);
+ $('#scr').addClass('ui-helper-hidden');
+ break;
+ default:
+ $(".statline").html(i18n.stat_ok.msgFormat(eventData.status));
+ $('#scr').removeClass('ui-helper-hidden');
+
+ $("#plugin_table > tbody > tr").remove();
+ for ( var idx in eventData.data ) {
+ entry( eventData.data[idx] );
+ }
+ $("#plugin_table").trigger("update");
+ if ( drawDetails ) renderDetails(eventData);
+ initStaticWidgets();
+ }
}
function entry( /* Object */ dataEntry ) {
- var trElement = tr( null, { id: "entry" + dataEntry.id } );
- entryInternal( trElement, dataEntry );
+ var trElement = tr( null, { id: "entry" + dataEntry.id } );
+ entryInternal( trElement, dataEntry );
$("#plugin_table > tbody").append(trElement);
}
@@ -59,64 +49,65 @@
var op = action.link;
var opLabel = action.name;
var img = action.image;
+ // fixup JQuery UI icons
+ if (img == 'configure') { img = 'wrench'
+ } else if (img == 'disable') { img = 'stop' //locked
+ } else if (img == 'enable') { img = 'play' //unlocked
+ }
+
+ // apply i18n
+ opLabel = i18n[opLabel] ? i18n[opLabel] : opLabel;
var arg = id;
if ( op == "configure" ) {
arg = pid
}
- var input = createElement( "input", null, {
- type: 'image',
- title: opLabel,
- alt: opLabel,
- src: imgRoot + '/component_' + img + '.png',
- style: {"margin-left": "10px"}
- });
- $(input).click(function() {changeDataEntryState(arg, op)});
+ var input = createElement('li', 'dynhover', {
+ title: opLabel
+ });
+ $(input)
+ .html('<span class="ui-icon ui-icon-'+img+'"></span>')
+ .click(function() {changeDataEntryState(arg, op)});
+
+ if (!enabled) {
+ $(input).attr('disabled', true).addClass('ui-state-disabled');
- if (!enabled) {
- $(input).attr("disabled", true);
- }
- parent.appendChild( input );
+ }
+ parent.appendChild( input );
}
function entryInternal( /* Element */ parent, /* Object */ dataEntry ) {
- var id = dataEntry.id;
- var name = dataEntry.name;
- var state = dataEntry.state;
-
- var inputElement = createElement("img", "rightButton", {
- src: appRoot + "/res/imgs/arrow_right.png",
- style: {"border": "none"},
- id: 'img' + id,
- title: "Details",
- alt: "Details",
- width: 14,
- height: 14
- });
+ var id = dataEntry.id;
+ var name = dataEntry.name;
+ var state = dataEntry.state;
+
+ var inputElement = createElement('span', 'ui-icon ui-icon-triangle-1-e', {
+ title: "Details",
+ id: 'img' + id,
+ style: {display: "inline-block"}
+ });
$(inputElement).click(function() {showDetails(id)});
- var titleElement;
- if ( drawDetails ) {
- titleElement = text(name);
- } else {
- titleElement = createElement ("a", null, {
- href: window.location.pathname + "/" + id
- });
- titleElement.appendChild(text(name));
- }
-
- parent.appendChild( td( null, null, [ text( id ) ] ) );
- parent.appendChild( td( null, null, [ inputElement, text(" "), titleElement ] ) );
- parent.appendChild( td( null, null, [ text( state ) ] ) );
- var actionsTd = td( null, null );
- var div = createElement("div", null, {
- style: { "text-align" : "left"}
- });
- actionsTd.appendChild(div);
-
- for ( var a in dataEntry.actions ) {
- actionButton( div, id, dataEntry.actions[a], dataEntry.pid );
- }
- parent.appendChild( actionsTd );
+ var titleElement;
+ if ( drawDetails ) {
+ titleElement = text(name);
+ } else {
+ titleElement = createElement ("a", null, {
+ href: window.location.pathname + "/" + id
+ });
+ titleElement.appendChild(text(name));
+ }
+
+ parent.appendChild( td( null, null, [ text( id ) ] ) );
+ parent.appendChild( td( null, null, [ inputElement, text(" "), titleElement ] ) );
+ parent.appendChild( td( null, null, [ text( state ) ] ) );
+ var actionsTd = td( null, null );
+ var div = createElement('ul', 'icons ui-widget');
+ actionsTd.appendChild(div);
+
+ for ( var a in dataEntry.actions ) {
+ actionButton( div, id, dataEntry.actions[a], dataEntry.pid );
+ }
+ parent.appendChild( actionsTd );
}
function changeDataEntryState(/* long */ id, /* String */ action) {
@@ -125,29 +116,31 @@
return;
}
$.post(pluginRoot + "/" + id, {"action":action}, function(data) {
- renderData(data);
+ renderData(data);
}, "json");
}
function showDetails( id ) {
- $.get(pluginRoot + "/" + id + ".json", null, function(data) {
- renderDetails(data);
- }, "json");
+ $.get(pluginRoot + "/" + id + ".json", null, function(data) {
+ renderDetails(data);
+ }, "json");
}
function loadData() {
$.get(pluginRoot + "/.json", null, function(data) {
- renderData(data);
+ renderData(data);
}, "json");
}
function hideDetails( id ) {
$("#img" + id).each(function() {
$("#pluginInlineDetails").remove();
- $(this).attr("src", appRoot + "/res/imgs/arrow_right.png");
- $(this).attr("title", "Details");
- $(this).attr("alt", "Details");
- $(this).unbind('click').click(function() {showDetails(id)});
+ $(this).
+ removeClass('ui-icon-triangle-1-w').//left
+ removeClass('ui-icon-triangle-1-s').//down
+ addClass('ui-icon-triangle-1-e').//right
+ attr("title", "Details").
+ unbind('click').click(function() {showDetails(id)});
});
}
@@ -157,73 +150,75 @@
$("#entry" + data.id + " > td").eq(1).append("<div id='pluginInlineDetails'/>");
$("#img" + data.id).each(function() {
if ( drawDetails ) {
- $(this).attr("src", appRoot + "/res/imgs/arrow_left.png");
- $(this).attr("title", "Back");
- $(this).attr("alt", "Back");
- var ref = window.location.pathname;
- ref = ref.substring(0, ref.lastIndexOf('/'));
- $(this).unbind('click').click(function() {window.location = ref;});
+ var ref = window.location.pathname;
+ ref = ref.substring(0, ref.lastIndexOf('/'));
+ $(this).
+ removeClass('ui-icon-triangle-1-e').//right
+ removeClass('ui-icon-triangle-1-s').//down
+ addClass('ui-icon-triangle-1-w').//left
+ attr("title", "Back").
+ unbind('click').click(function() {window.location = ref});
} else {
- $(this).attr("src", appRoot + "/res/imgs/arrow_down.png");
- $(this).attr("title", "Hide Details");
- $(this).attr("alt", "Hide Details");
- $(this).unbind('click').click(function() {hideDetails(data.id)});
+ $(this).
+ removeClass('ui-icon-triangle-1-w').//left
+ removeClass('ui-icon-triangle-1-e').//right
+ addClass('ui-icon-triangle-1-s').//down
+ attr("title", "Hide Details").
+ unbind('click').click(function() {hideDetails(data.id)});
}
});
$("#pluginInlineDetails").append("<table border='0'><tbody></tbody></table>");
- var details = data.props;
- for (var idx in details) {
- var prop = details[idx];
-
- var txt = "<tr><td class='aligntop' noWrap='true' style='border:0px none'>" + prop.key + "</td><td class='aligntop' style='border:0px none'>";
- if (prop.value) {
- if ( $.isArray(prop.value) ) {
- var i = 0;
- for(var pi in prop.value) {
- var value = prop.value[pi];
- if (i > 0) { txt = txt + "<br/>"; }
- var span;
- if (value.substring(0, 2) == "!!") {
- txt = txt + "<span style='color: red;'>" + value + "</span>";
- } else {
- txt = txt + value;
- }
- i++;
- }
- } else {
- txt = txt + prop.value;
- }
- } else {
- txt = txt + "\u00a0";
- }
- txt = txt + "</td></tr>";
- $("#pluginInlineDetails > table > tbody").append(txt);
+ var details = data.props;
+ for (var idx in details) {
+ var prop = details[idx];
+ var key = i18n[prop.key] ? i18n[prop.key] : prop.key; // i18n
+
+ var txt = "<tr><td class='aligntop' noWrap='true' style='border:0px none'>" + key + "</td><td class='aligntop' style='border:0px none'>";
+ if (prop.value) {
+ if ( $.isArray(prop.value) ) {
+ var i = 0;
+ for(var pi in prop.value) {
+ var value = prop.value[pi];
+ if (i > 0) { txt = txt + "<br/>"; }
+ var span;
+ if (value.substring(0, 2) == "!!") {
+ txt = txt + "<span style='color: red;'>" + value + "</span>";
+ } else {
+ txt = txt + value;
+ }
+ i++;
+ }
+ } else {
+ txt = txt + prop.value;
+ }
+ } else {
+ txt = txt + "\u00a0";
+ }
+ txt = txt + "</td></tr>";
+ $("#pluginInlineDetails > table > tbody").append(txt);
}
}
-function renderComponents(data) {
- $(document).ready(function(){
- renderView( ["Id", "Name", "Status", "Actions"],
- "<div class='button'><button class='reloadButton' type='button' name='reload'>Reload</button></div>");
- renderData(data);
-
- $(".reloadButton").click(loadData);
- var extractMethod = function(node) {
- var link = node.getElementsByTagName("a");
- if ( link && link.length == 1 ) {
- return link[0].innerHTML;
- }
- return node.innerHTML;
- };
- $("#plugin_table").tablesorter({
- headers: {
- 0: { sorter:"digit"},
- 3: { sorter: false }
- },
- sortList: [[1,0]],
- textExtraction:extractMethod
- });
- });
-}
-
+$(document).ready(function(){
+ renderData (scrData);
+
+ $(".reloadButton").click(loadData);
+
+ var extractMethod = function(node) {
+ var link = node.getElementsByTagName("a");
+ if ( link && link.length == 1 ) {
+ return link[0].innerHTML;
+ }
+ return node.innerHTML;
+ };
+ $("#plugin_table").tablesorter({
+ headers: {
+ 0: { sorter:"digit"},
+ 3: { sorter: false }
+ },
+ sortList: [[1,0]],
+ textExtraction:extractMethod
+ });
+});
+
diff --git a/webconsole/src/main/resources/templates/components.html b/webconsole/src/main/resources/templates/components.html
new file mode 100644
index 0000000..b995d31
--- /dev/null
+++ b/webconsole/src/main/resources/templates/components.html
@@ -0,0 +1,54 @@
+<script type="text/javascript" src="res/ui/components.js"></script>
+<script type="text/javascript">
+// <![CDATA[
+var drawDetails = ${__drawDetails__};
+var scrData = ${__data__};
+// i18n
+var i18n = {
+ 'Enable' : '${scr.action.enable}',
+ 'Disable' : '${scr.action.disable}',
+ 'Configure' : '${scr.action.configure}',
+ 'Bundle' : '${scr.prop.bundle}',
+ 'Default State' : '${scr.prop.defstate}',
+ 'Activation' : '${scr.prop.activation}',
+ 'Service Type' : '${scr.serv.type}',
+ 'Services' : '${scr.serv}',
+ 'Properties' : '${scr.prop.properties}',
+ stat_no_service : "${scr.status.no_service}",
+ stat_no_components : "${scr.status.no_components}",
+ stat_ok : "${scr.status.ok}"
+}
+// ]]>
+</script>
+<p class="statline"> </p>
+
+
+<div id="scr"> <!-- data available -->
+ <!-- top header -->
+ <form method='post' enctype='multipart/form-data' action="">
+ <div class="ui-widget-header ui-corner-top buttonGroup">
+ <button class='reloadButton' type='button' name='reload'>${reload}</button>
+ </div>
+ </form>
+
+ <table id="plugin_table" class="tablesorter nicetable noauto">
+ <thead>
+ <tr>
+ <th class="col_Id">${id}</th>
+ <th class="col_Name">${scr.title.name}</th>
+ <th class="col_Status">${scr.title.status}</th>
+ <th class="col_Actions">${scr.title.actions}</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr><td colspan="4"> </td></tr>
+ </tbody>
+ </table>
+</div> <!-- end data available -->
+
+<!-- bottom header -->
+<form method='post' enctype='multipart/form-data' action="">
+ <div class="ui-widget-header ui-corner-bottom buttonGroup">
+ <button class='reloadButton' type='button' name='reload'>${reload}</button>
+ </div>
+</form>
\ No newline at end of file