felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From vvalc...@apache.org
Subject svn commit: r1172536 - in /felix/trunk/webconsole-plugins/event/src/main: java/org/apache/felix/webconsole/plugins/event/internal/ native2ascii/OSGI-INF/l10n/ resources/OSGI-INF/l10n/ resources/res/ resources/res/ui/
Date Mon, 19 Sep 2011 09:32:51 GMT
Author: vvalchev
Date: Mon Sep 19 09:32:50 2011
New Revision: 1172536

URL: http://svn.apache.org/viewvc?rev=1172536&view=rev
Log:
FELIX-2331 : webconsole event plugin should be able to send/post events.
https://issues.apache.org/jira/browse/FELIX-2331

Added:
    felix/trunk/webconsole-plugins/event/src/main/java/org/apache/felix/webconsole/plugins/event/internal/PropertiesEditorSupport.java
  (with props)
    felix/trunk/webconsole-plugins/event/src/main/resources/res/ui/addremove.js   (with props)
    felix/trunk/webconsole-plugins/event/src/main/resources/res/ui/propeditor.js   (with props)
Modified:
    felix/trunk/webconsole-plugins/event/src/main/java/org/apache/felix/webconsole/plugins/event/internal/OptionalFeaturesHandler.java
    felix/trunk/webconsole-plugins/event/src/main/java/org/apache/felix/webconsole/plugins/event/internal/PluginServlet.java
    felix/trunk/webconsole-plugins/event/src/main/native2ascii/OSGI-INF/l10n/bundle_bg.properties
    felix/trunk/webconsole-plugins/event/src/main/resources/OSGI-INF/l10n/bundle.properties
    felix/trunk/webconsole-plugins/event/src/main/resources/res/events.html
    felix/trunk/webconsole-plugins/event/src/main/resources/res/ui/events.css
    felix/trunk/webconsole-plugins/event/src/main/resources/res/ui/events.js

Modified: felix/trunk/webconsole-plugins/event/src/main/java/org/apache/felix/webconsole/plugins/event/internal/OptionalFeaturesHandler.java
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/event/src/main/java/org/apache/felix/webconsole/plugins/event/internal/OptionalFeaturesHandler.java?rev=1172536&r1=1172535&r2=1172536&view=diff
==============================================================================
--- felix/trunk/webconsole-plugins/event/src/main/java/org/apache/felix/webconsole/plugins/event/internal/OptionalFeaturesHandler.java
(original)
+++ felix/trunk/webconsole-plugins/event/src/main/java/org/apache/felix/webconsole/plugins/event/internal/OptionalFeaturesHandler.java
Mon Sep 19 09:32:50 2011
@@ -21,6 +21,7 @@ import java.util.Dictionary;
 import java.util.Hashtable;
 
 import org.osgi.framework.*;
+import org.osgi.service.event.EventAdmin;
 
 /**
  * This class handles all optional stuff.
@@ -30,15 +31,16 @@ import org.osgi.framework.*;
 public class OptionalFeaturesHandler
     implements ServiceListener
 {
-    private static final String EVENT_ADMIN_CLASS_NAME = "org.osgi.service.event.EventAdmin";
-    private static final String CONFIGURATION_ADMIN_CLASS_NAME = "org.osgi.service.cm.ConfigurationAdmin";
-    private static final String EVENT_HANDLER_CLASS_NAME = "org.osgi.service.event.EventHandler";
+    private static final String EVENT_ADMIN_CLASS_NAME = "org.osgi.service.event.EventAdmin";
//$NON-NLS-1$
+    private static final String CONFIGURATION_ADMIN_CLASS_NAME = "org.osgi.service.cm.ConfigurationAdmin";
//$NON-NLS-1$
+    private static final String EVENT_HANDLER_CLASS_NAME = "org.osgi.service.event.EventHandler";
//$NON-NLS-1$
 
     private static final String FILTER = "(|(" + Constants.OBJECTCLASS + "=" + EVENT_ADMIN_CLASS_NAME
+ ")"
                                         +"(" + Constants.OBJECTCLASS + "=" + CONFIGURATION_ADMIN_CLASS_NAME
+ "))";
 
     /** Event admin service id */
-    private Long eventAdminServiceId;
+    //private Long eventAdminServiceId;
+    private ServiceReference eventAdminServiceRef;
 
     /** Registration for the event handler. */
     private ServiceRegistration eventHandlerRegistration;
@@ -60,12 +62,10 @@ public class OptionalFeaturesHandler
         this.plugin = plugin;
         this.bundleContext = context;
         // check if event admin is already available
-        this.eventAdminServiceId = null;
         final ServiceReference ref = this.bundleContext.getServiceReference(EVENT_ADMIN_CLASS_NAME);
         if ( ref != null )
         {
-            final Long id = (Long)ref.getProperty(Constants.SERVICE_ID);
-            bindEventAdmin(id);
+            bindEventAdmin(ref);
         }
 
         // check if config admin is already available
@@ -91,7 +91,7 @@ public class OptionalFeaturesHandler
     public void destroy()
     {
         this.bundleContext.removeServiceListener(this);
-        this.unbindEventAdmin(this.eventAdminServiceId);
+        this.unbindEventAdmin(this.eventAdminServiceRef);
         this.unbindConfigAdmin(this.configAdminServiceId);
     }
 
@@ -100,14 +100,14 @@ public class OptionalFeaturesHandler
      */
     public void serviceChanged(final ServiceEvent event)
     {
-        final String[] objectClasses =  (String[])event.getServiceReference().getProperty(Constants.OBJECTCLASS);
+        final ServiceReference ref = event.getServiceReference();
+        final String[] objectClasses =  (String[])ref.getProperty(Constants.OBJECTCLASS);
         if ( objectClasses != null)
         {
             for(int i=0; i<objectClasses.length; i++)
             {
                 if ( objectClasses[i].equals(EVENT_ADMIN_CLASS_NAME) )
                 {
-                    final Long id = (Long)event.getServiceReference().getProperty(Constants.SERVICE_ID);
                     if ( event.getType() == ServiceEvent.REGISTERED )
                     {
                         new Thread()
@@ -117,7 +117,7 @@ public class OptionalFeaturesHandler
                                 try {
                                     Thread.sleep(500);
                                 } catch (InterruptedException ignore) {}
-                                bindEventAdmin(id);
+                                bindEventAdmin(ref);
                             }
                         }.start();
                     }
@@ -130,7 +130,7 @@ public class OptionalFeaturesHandler
                                 try {
                                     Thread.sleep(500);
                                 } catch (InterruptedException ignore) {}
-                                unbindEventAdmin(id);
+                                unbindEventAdmin(ref);
                             }
                         }.start();
                     }
@@ -169,29 +169,30 @@ public class OptionalFeaturesHandler
         }
     }
 
-    private synchronized void bindEventAdmin(final Long id)
+    synchronized void bindEventAdmin(ServiceReference ref)
     {
-        if ( this.eventAdminServiceId != null)
+        if ( this.eventAdminServiceRef != null)
         {
-            this.unbindEventAdmin(this.eventAdminServiceId);
+            this.unbindEventAdmin(this.eventAdminServiceRef);
         }
-        this.eventAdminServiceId = id;
+        this.eventAdminServiceRef = ref;
         final Dictionary props = new Hashtable();
         props.put( Constants.SERVICE_DESCRIPTION, "Event handler for the Apache Felix Web
Console" );
         props.put( Constants.SERVICE_VENDOR, "The Apache Software Foundation" );
-        props.put( "event.topics", "*");
-        this.plugin.setEventAdminAvailable(true);
+        props.put( "event.topics", "*"); //$NON-NLS-1$ //$NON-NLS-2$
+        this.plugin.setEventAdmin((EventAdmin) bundleContext.getService(ref));
 
         this.eventHandlerRegistration = this.bundleContext.registerService(EVENT_HANDLER_CLASS_NAME,
                 new EventHandler(this.plugin.getCollector()), props);
     }
 
-    private synchronized void unbindEventAdmin(final Long id)
+    synchronized void unbindEventAdmin(ServiceReference ref)
     {
-        if ( this.eventAdminServiceId != null && this.eventAdminServiceId.equals(id)
)
+        if ( this.eventAdminServiceRef != null && this.eventAdminServiceRef.equals(ref)
)
         {
-            this.eventAdminServiceId = null;
-            this.plugin.setEventAdminAvailable(false);
+            bundleContext.ungetService(ref);
+            this.eventAdminServiceRef = null;
+            this.plugin.setEventAdmin(null);
             if ( this.eventHandlerRegistration != null )
             {
                 this.eventHandlerRegistration.unregister();
@@ -200,7 +201,7 @@ public class OptionalFeaturesHandler
         }
     }
 
-    private synchronized void bindConfigAdmin(final Long id)
+    synchronized void bindConfigAdmin(final Long id)
     {
         if ( this.configAdminServiceId != null )
         {
@@ -211,7 +212,7 @@ public class OptionalFeaturesHandler
         this.configListenerRegistration = ConfigurationListener.create(this.bundleContext,
this.plugin);
     }
 
-    private synchronized void unbindConfigAdmin(final Long id)
+    synchronized void unbindConfigAdmin(final Long id)
     {
         if ( this.configAdminServiceId != null && this.configAdminServiceId.equals(id)
)
         {

Modified: felix/trunk/webconsole-plugins/event/src/main/java/org/apache/felix/webconsole/plugins/event/internal/PluginServlet.java
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/event/src/main/java/org/apache/felix/webconsole/plugins/event/internal/PluginServlet.java?rev=1172536&r1=1172535&r2=1172536&view=diff
==============================================================================
--- felix/trunk/webconsole-plugins/event/src/main/java/org/apache/felix/webconsole/plugins/event/internal/PluginServlet.java
(original)
+++ felix/trunk/webconsole-plugins/event/src/main/java/org/apache/felix/webconsole/plugins/event/internal/PluginServlet.java
Mon Sep 19 09:32:50 2011
@@ -28,30 +28,35 @@ import java.util.Map.Entry;
 import javax.servlet.ServletException;
 import javax.servlet.http.*;
 
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventAdmin;
+
 /**
  * The Event Plugin
  */
 public class PluginServlet extends HttpServlet
 {
-    private static final String ACTION_CLEAR = "clear";
+    
+    private static final String ACTION_POST = "post"; //$NON-NLS-1$
+    private static final String ACTION_SEND = "send"; //$NON-NLS-1$
+    private static final String ACTION_CLEAR = "clear"; //$NON-NLS-1$
 
-    private static final String PARAMETER_ACTION = "action";
+    private static final String PARAMETER_ACTION = "action"; //$NON-NLS-1$
 
     /** The event collector. */
     private final EventCollector collector;
 
-    /** Is the event admin available? */
-    private volatile boolean eventAdminAvailable = false;
-
     /** Is the config admin available? */
     private volatile boolean configAdminAvailable = false;
     
+    private EventAdmin eventAdmin;
+
     private final String TEMPLATE;
 
     public PluginServlet()
     {
         this.collector = new EventCollector(null);
-        TEMPLATE = readTemplateFile(getClass(), "/res/events.html");
+        TEMPLATE = readTemplateFile(getClass(), "/res/events.html"); //$NON-NLS-1$
     }
     
     private final String readTemplateFile(final Class clazz, final String templateFile)
@@ -68,7 +73,7 @@ public class PluginServlet extends HttpS
                 {
                     baos.write(data, 0, len);
                 }
-                return baos.toString("UTF-8");
+                return baos.toString("UTF-8"); //$NON-NLS-1$
             }
             catch (IOException e)
             {
@@ -93,9 +98,17 @@ public class PluginServlet extends HttpS
         // template file does not exist, return an empty string
         log("readTemplateFile: File '" + templateFile + "' not found through class "
             + clazz);
-        return "";
+        return ""; //$NON-NLS-1$
     }
+    
+    private static final Event newEvent(HttpServletRequest request)
+    {
+        String topic = request.getParameter("topic"); //$NON-NLS-1$
 
+        return new Event(topic, (Dictionary)PropertiesEditorSupport.convertProperties(request));
+    }
+    
+   
     /**
      * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest,
javax.servlet.http.HttpServletResponse)
      */
@@ -103,14 +116,18 @@ public class PluginServlet extends HttpS
     throws ServletException, IOException
     {
         final String action = req.getParameter( PARAMETER_ACTION );
-        // for now we only have the clear action
-        if ( ACTION_CLEAR.equals( action ) )
-        {
+        if ( ACTION_POST.equals(action) ) {
+            final Event event = newEvent(req);
+            eventAdmin.postEvent(event);
+        } else if (ACTION_SEND.equals(action)) {
+            final Event event = newEvent(req);
+            eventAdmin.sendEvent(event);
+        } else if ( ACTION_CLEAR.equals( action ) ) {
             this.collector.clear();
         }
         // we always send back the json data
-        resp.setContentType( "application/json" );
-        resp.setCharacterEncoding( "utf-8" );
+        resp.setContentType( "application/json" ); //$NON-NLS-1$
+        resp.setCharacterEncoding( "utf-8" ); //$NON-NLS-1$
 
         renderJSON( resp.getWriter() );
     }
@@ -135,7 +152,7 @@ public class PluginServlet extends HttpS
             statusLine.append( d );
         }
         statusLine.append( ". (Event admin: " );
-        if ( !this.eventAdminAvailable )
+        if ( this.eventAdmin == null )
         {
             statusLine.append("un");
         }
@@ -172,7 +189,7 @@ public class PluginServlet extends HttpS
 
         pw.write(']');
 
-        pw.write("}");
+        pw.write("}"); //$NON-NLS-1$
     }
 
 
@@ -181,10 +198,10 @@ public class PluginServlet extends HttpS
     {
 
         final String info = request.getPathInfo();
-        if ( info.endsWith( ".json" ) )
+        if ( info.endsWith( ".json" ) ) //$NON-NLS-1$
         {
-            response.setContentType( "application/json" );
-            response.setCharacterEncoding( "UTF-8" );
+            response.setContentType( "application/json" ); //$NON-NLS-1$
+            response.setCharacterEncoding( "UTF-8" ); //$NON-NLS-1$
 
             PrintWriter pw = response.getWriter();
             this.renderJSON( pw );
@@ -208,7 +225,7 @@ public class PluginServlet extends HttpS
 
     public URL getResource(String path)
     {
-        if ( path.startsWith("/events/res/ui/") )
+        if ( path.startsWith("/events/res/ui/") ) //$NON-NLS-1$
         {
             return this.getClass().getResource(path.substring(7));
         }
@@ -374,9 +391,9 @@ public class PluginServlet extends HttpS
         return this.collector;
     }
 
-    public void setEventAdminAvailable(final boolean flag)
+    public void setEventAdmin(final EventAdmin eventAdmin)
     {
-        this.eventAdminAvailable = flag;
+        this.eventAdmin = eventAdmin;
     }
 
     public void setConfigAdminAvailable(final boolean flag)

Added: felix/trunk/webconsole-plugins/event/src/main/java/org/apache/felix/webconsole/plugins/event/internal/PropertiesEditorSupport.java
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/event/src/main/java/org/apache/felix/webconsole/plugins/event/internal/PropertiesEditorSupport.java?rev=1172536&view=auto
==============================================================================
--- felix/trunk/webconsole-plugins/event/src/main/java/org/apache/felix/webconsole/plugins/event/internal/PropertiesEditorSupport.java
(added)
+++ felix/trunk/webconsole-plugins/event/src/main/java/org/apache/felix/webconsole/plugins/event/internal/PropertiesEditorSupport.java
Mon Sep 19 09:32:50 2011
@@ -0,0 +1,95 @@
+/*
+ * 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.
+ */
+package org.apache.felix.webconsole.plugins.event.internal;
+
+import java.util.Hashtable;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Java support for propeditor.js handling.
+ */
+public class PropertiesEditorSupport
+{
+
+    private PropertiesEditorSupport()
+    {
+        // prevent instantiation
+    }
+
+    /**
+     * Converts the properties from the request to a key-value hashtable.
+     * 
+     * @param request the request to process
+     * @return the converted properties
+     */
+    public static final Hashtable convertProperties(HttpServletRequest request)
+    {
+        String keys[] = request.getParameterValues("key"); //$NON-NLS-1$
+        String vals[] = request.getParameterValues("val"); //$NON-NLS-1$
+        String types[] = request.getParameterValues("type"); //$NON-NLS-1$
+
+        final Hashtable properties = new Hashtable();
+        synchronized (properties)
+        {
+            for (int i = 0; keys != null && i < keys.length; i++)
+            {
+                properties.put(keys[i], convert(vals[i], types[i]));
+            }
+        }
+
+        return properties;
+    }
+
+    private static final Object convert(String value, String type)
+    {
+        if ("byte".equals(type)) //$NON-NLS-1$
+        {
+            return Byte.valueOf(value);
+        }
+        else if ("int".equals(type)) //$NON-NLS-1$
+        {
+            return Integer.valueOf(value);
+        }
+        else if ("long".equals(type)) //$NON-NLS-1$
+        {
+            return Long.valueOf(value);
+        }
+        else if ("float".equals(type)) //$NON-NLS-1$
+        {
+            return Float.valueOf(value);
+        }
+        else if ("double".equals(type)) //$NON-NLS-1$
+        {
+            return Double.valueOf(value);
+        }
+        else if ("string".equals(type)) //$NON-NLS-1$
+        {
+            return value.toString();
+        }
+        else if ("char".equals(type)) //$NON-NLS-1$
+        {
+            return Character.valueOf(value.toString().charAt(0));
+        }
+        else
+        {
+            throw new IllegalArgumentException("Unsupported type!");
+        }
+        // TODO: hex, base64, sha1
+    }
+
+}

Propchange: felix/trunk/webconsole-plugins/event/src/main/java/org/apache/felix/webconsole/plugins/event/internal/PropertiesEditorSupport.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: felix/trunk/webconsole-plugins/event/src/main/native2ascii/OSGI-INF/l10n/bundle_bg.properties
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/event/src/main/native2ascii/OSGI-INF/l10n/bundle_bg.properties?rev=1172536&r1=1172535&r2=1172536&view=diff
==============================================================================
--- felix/trunk/webconsole-plugins/event/src/main/native2ascii/OSGI-INF/l10n/bundle_bg.properties
(original)
+++ felix/trunk/webconsole-plugins/event/src/main/native2ascii/OSGI-INF/l10n/bundle_bg.properties
Mon Sep 19 09:32:50 2011
@@ -38,3 +38,10 @@ topic=Тема
 properties=Атрибути
 
 plugin.events.title=Събития
+
+# send event
+sendEvent=Изпращане
+post=Прати
+send=Прати веднага
+close=Затваряне
+

Modified: felix/trunk/webconsole-plugins/event/src/main/resources/OSGI-INF/l10n/bundle.properties
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/event/src/main/resources/OSGI-INF/l10n/bundle.properties?rev=1172536&r1=1172535&r2=1172536&view=diff
==============================================================================
--- felix/trunk/webconsole-plugins/event/src/main/resources/OSGI-INF/l10n/bundle.properties
(original)
+++ felix/trunk/webconsole-plugins/event/src/main/resources/OSGI-INF/l10n/bundle.properties
Mon Sep 19 09:32:50 2011
@@ -37,4 +37,10 @@ received=Received
 topic=Event Topic
 properties=Event Properties
 
-plugin.events.title=Events
\ No newline at end of file
+plugin.events.title=Events
+
+# send event
+sendEvent=Send/Post Event
+post=Post Event
+send=Send Event
+close=Close

Modified: felix/trunk/webconsole-plugins/event/src/main/resources/res/events.html
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/event/src/main/resources/res/events.html?rev=1172536&r1=1172535&r2=1172536&view=diff
==============================================================================
--- felix/trunk/webconsole-plugins/event/src/main/resources/res/events.html (original)
+++ felix/trunk/webconsole-plugins/event/src/main/resources/res/events.html Mon Sep 19 09:32:50
2011
@@ -1,8 +1,13 @@
-<script type="text/javascript" src="${pluginRoot}/res/ui/events.js"></script>
+<script type="text/javascript" src="${pluginRoot}/res/ui/addremove.js"></script>
+<script type="text/javascript" src="${pluginRoot}/res/ui/propeditor.js"></script>
+<script type="text/javascript" src="${pluginRoot}/res/ui/events.js"></script>
 <script type="text/javascript">
 var i18n = {
 	displayTimeline: '${displayTimeline}',
-	displayList    : '${displayList}'
+	displayList    : '${displayList}',
+	close          : '${close}',
+	send           : '${send}',
+	post           : '${post}'
 }
 </script>
 
@@ -13,6 +18,7 @@ var i18n = {
 <div class="ui-widget-header ui-corner-top buttonGroup">
 	<button id="switch">${displayTimeline}</button>
 	<button id="clear">${clear}</button>
+	<button id="sendButton">${sendEvent}</button>
 	<button id="reload">${reload}</button>
 </div>
 
@@ -35,9 +41,27 @@ var i18n = {
 </table>
 
 <div id="timeline" class="ui-helper-hidden">&nbsp;</div>
+
 <div id="timelineLegend" class="ui-helper-hidden">
 	<span class="event eventservice">Service Event</span>
 	<span class="event eventbundle">Bundle Event</span>
 	<span class="event eventconfig">Config Event</span>
 	<span class="event eventframework">Framework Event</span>
 </div>
+
+<div id="sendDialog" title="${sendEvent}" class="ui-helper-hidden">
+	<table>
+	<tbody>
+		<tr>
+			<th>${topic}:</th>
+			<td><input id="sendTopic"/></td>
+		</tr>
+		<tr>
+			<th>${properties}:</th>
+			<td>
+				<div id="sendProperties">&nbsp;</div>
+			</td>
+		</tr>
+	</tbody>
+	</table>
+</div>

Added: felix/trunk/webconsole-plugins/event/src/main/resources/res/ui/addremove.js
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/event/src/main/resources/res/ui/addremove.js?rev=1172536&view=auto
==============================================================================
--- felix/trunk/webconsole-plugins/event/src/main/resources/res/ui/addremove.js (added)
+++ felix/trunk/webconsole-plugins/event/src/main/resources/res/ui/addremove.js Mon Sep 19
09:32:50 2011
@@ -0,0 +1,99 @@
+/*
+	Structure is:
+	<div class="my-element-container">
+		<div class="multiInput">
+			<div id="myElement" /> + -
+		</div>
+	</div>
+	
+	Options:
+	add : function(element) - called AFTER add
+	remove : function(element) - called BEFORE remove
+*/
+(function( $ ){
+
+	var methods = {
+		init : function(options) {
+			return this.each( function() {
+				// If options exist, lets merge them with our default settings
+				var settings = {
+					add    : false,
+					remove : false
+				};
+				if (options) settings = $.extend(settings, options);
+				
+				var _this = $(this);
+				var template = _init_template( _this );
+				_this.data('addremove_settings', settings);
+				_new_entry(template, _this);
+			})
+		},
+		reset : function() {
+			return this.each( function() {
+				var self = $(this);
+				self.find('div.addremove').not(':first').each( function() {
+					$(this).find('button.rem').click();
+				});
+			});
+		},
+		add : function(count) {
+			return this.each( function() {
+				var self = $(this);
+				var addfn = self.find('div.addremove:last button.add');
+				if (addfn.size()) {
+					var num = count ? count : 1;
+					for(var i=0; i<num; i++) addfn.click();
+				}
+			});
+		},
+		count : function() {
+			var self = $(this);
+			return $(this).find('div.addremove').size();
+		}
+	};
+
+	$.fn.addremove = function( method ) {
+		// Method calling logic
+		if ( methods[method] ) {
+		  return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
+		} else if ( typeof method === 'object' || ! method ) {
+		  return methods.init.apply( this, arguments );
+		} else {
+		  $.error( 'Method ' +  method + ' does not exist on jQuery.addremove' );
+		} 
+	};
+	
+	var _new_entry = function(template, container) {
+		var settings = container.data('addremove_settings');
+		var _entry = template.clone()
+			.find('button.add').click( function() {
+				_new_entry(template, container);
+				return false;
+			}).end()
+			.find('button.rem').click( function() {
+				if (container.addremove('count') > 1) {
+					if (typeof settings.remove == 'function') {
+						settings.remove(_entry);
+					}
+					_entry.remove();
+				}
+				return false;
+			}).end()
+			.appendTo(container);
+		if (typeof settings.add == 'function') settings.add(_entry);
+	}
+
+	var _init_template = function(entry) {
+		return _el('div', 'addremove')
+			.append(entry.children())
+			.append(_el('button', 'add').text('+'))
+			.append(_el('button', 'rem').text('-'));
+	}
+
+	var _el = function(el, clazz) {
+		var ret = $(document.createElement(el));
+		if (clazz) ret.addClass(clazz);
+		return ret;
+	}
+
+})( jQuery );
\ No newline at end of file

Propchange: felix/trunk/webconsole-plugins/event/src/main/resources/res/ui/addremove.js
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: felix/trunk/webconsole-plugins/event/src/main/resources/res/ui/events.css
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/event/src/main/resources/res/ui/events.css?rev=1172536&r1=1172535&r2=1172536&view=diff
==============================================================================
--- felix/trunk/webconsole-plugins/event/src/main/resources/res/ui/events.css (original)
+++ felix/trunk/webconsole-plugins/event/src/main/resources/res/ui/events.css Mon Sep 19 09:32:50
2011
@@ -24,4 +24,13 @@
 
 table.propTable, table.propTable tr, table.propTable td { border: none !important }
 td.propName { padding: 0 4px 0 0; text-align: right !important; text-decoration: underline
}
-td.propVal   { padding: 0 0 0 4px }
\ No newline at end of file
+td.propVal   { padding: 0 0 0 4px }
+td.time { white-space: nowrap }
+
+/* send dialog styling */
+.addremove button { width: 16px; height: 16px; line-height: 10px; font-size: 10px; margin:
2px 2px }
+.addremove_inner { display: inline }
+.propeditor_entry select {	margin-left: 4px }
+#sendTopic { width: 100% }
+#sendDialog table { margin-left: auto; margin-right: auto }
+#sendDialog table th { text-align: right; font-weight: bold; padding-right: .5em }

Modified: felix/trunk/webconsole-plugins/event/src/main/resources/res/ui/events.js
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/event/src/main/resources/res/ui/events.js?rev=1172536&r1=1172535&r2=1172536&view=diff
==============================================================================
--- felix/trunk/webconsole-plugins/event/src/main/resources/res/ui/events.js (original)
+++ felix/trunk/webconsole-plugins/event/src/main/resources/res/ui/events.js Mon Sep 19 09:32:50
2011
@@ -62,9 +62,9 @@ function entry( /* Object */ dataEntry )
     }
 
 	$(tr( null, { id: 'entry' + dataEntry.id }, [
-		td( null, null, [ text( printDate(dataEntry.received) ) ] ),
-		td( null, null, [ text( dataEntry.topic ) ] ),
-		td( null, null, [ propE ] )
+		td( 'time', null, [ text( printDate(dataEntry.received) ) ] ),
+		td( 'topic', null, [ text( dataEntry.topic ) ] ),
+		td( 'detailes', null, [ propE ] )
 	])).appendTo(eventsBody);
 }
 
@@ -96,4 +96,60 @@ $(document).ready(function(){
 	$('#reload').click(function() {
 		$.get(pluginRoot + '/data.json', null, renderData, 'json');
 	}).click();
+
+	function sendData(action) {
+		// check topic
+		var topic = sendTopic.val();
+		var topicOk = topic.match(/^[\w-]+(\/[\w-]+)*$/g) != null;
+		if (topicOk) {
+			sendTopic.removeClass('ui-state-error');
+		} else {
+			addTopic.removeClass('ui-state-error');
+		}
+		var data = sendProperties.propeditor('serialize');
+		if (topicOk && data != false) {
+			$.post(pluginRoot,
+				data.concat([
+					{name : 'action', value : action},
+					{name : 'topic', value : topic}
+				]),
+				renderData,
+				'json'
+			);
+			sendDialog.dialog("close");
+		}
+	}
+
+	/* send dialog code */
+	var sendButtons = {};
+	sendButtons[i18n.close] = function() {
+		$(this).dialog("close");
+	}
+	sendButtons[i18n.send] = function() {
+		sendData('send');
+	}
+	sendButtons[i18n.post] = function() {
+		sendData('post');
+	}
+	var sendDialog = $('#sendDialog').dialog({
+		autoOpen: false,
+		modal   : true,
+		width   : '40%',
+		buttons : sendButtons,
+		open    : function() {
+			sendTopic.val('');
+			sendProperties.propeditor('reset');
+		}
+	});
+	var sendTopic = $('#sendTopic');
+	var sendProperties = $('#sendProperties').propeditor({
+		add: function(el) {
+			el.find('select').addClass('dynhover');
+			initStaticWidgets(el);
+		}
+	});
+	$('#sendButton').click(function() {
+		sendDialog.dialog('open');
+	});
+
 });

Added: felix/trunk/webconsole-plugins/event/src/main/resources/res/ui/propeditor.js
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/event/src/main/resources/res/ui/propeditor.js?rev=1172536&view=auto
==============================================================================
--- felix/trunk/webconsole-plugins/event/src/main/resources/res/ui/propeditor.js (added)
+++ felix/trunk/webconsole-plugins/event/src/main/resources/res/ui/propeditor.js Mon Sep 19
09:32:50 2011
@@ -0,0 +1,193 @@
+/*
+	Structure is:
+	<div class="propeditor">
+		<div>
+			<input class="key"/> = 
+			<input class="value"/>
+			<select>
+				<option>byte</option>
+				<option>int</option>
+				<option>long</option>
+				<option>float</option>
+				<option>double</option>
+				<option>string</option>
+				<option>char</option>
+				<option>hex</option>
+				<option>sha1</option>
+				<option>base64</option>
+			</select>
+		</div>
+	</div>
+	
+	Options:
+	validator : function(keyInputField, valInputField, type)
+*/
+(function( $ ){
+	var TYPES = ['byte', 'int', 'long', 'float', 'double', 'string', 'char', 'hex', 'base64',
'sha1'];
+
+	var methods = {
+		init : function(options) {
+			return this.each( function() {
+				// If options exist, lets merge them with our default settings
+				var settings = {
+					validator  : false,
+				};
+				if (options) settings = $.extend(settings, options);
+
+				var _this = $(this);
+				_this.data('propeditor_settings', settings);
+				_this.append(_entry());
+				_this.addremove(settings);
+			})
+		},
+		reset : function() {
+			return this.each( function() {
+				$(this).addremove('reset')
+					.find('.key').val('').end()
+					.find('.val').val('');
+			});
+		},
+		serialize : function() {
+			var self = $(this);
+			var validator = self.data('propeditor_settings').validator;
+			var result = new Array();
+			var ok = true;
+			var entries = $(this).find('div.addremove');
+			if (entries.size() == 1) {
+				var k = entries.find('.key').removeClass('ui-state-error').val();
+				var v = entries.find('.val').removeClass('ui-state-error').val();
+				if (k != '' || v != '') {
+					var data = _check_entry( entries, validator );
+					//if ( data == false ) ok = false; else result.push(data);
+					if ( data == false ) ok = false; else result = data;
+				}
+			} else {
+				entries.each(function() {
+					var data = _check_entry( $(this), validator );
+					//if ( data == false ) ok = false; else result.push(data);
+					if ( data == false ) ok = false; else result = result.concat(data);
+				});
+			}
+			return ok ? result : false;
+		},
+		setup : function(data, append) {
+			var self = $(this);
+			if (!append) self.propeditor('reset');
+			for (var i in data) {
+				self.addremove('add');
+				var d = data[i];
+				self.find('div.addremove:last')
+					.find('.key').val(d.key).end()
+					.find('.val').val(d.val).end()
+					.find('.typ').val(d.type);
+			}
+			if (!append) self.find('div.addremove:first').remove();
+		}
+	};
+
+	$.fn.propeditor = function( method ) {
+		// Method calling logic
+		if ( methods[method] ) {
+		  return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
+		} else if ( typeof method === 'object' || ! method ) {
+		  return methods.init.apply( this, arguments );
+		} else {
+		  $.error( 'Method ' +  method + ' does not exist on jQuery.tooltip' );
+		} 
+	};
+
+	var _el = function(el, clazz) {
+		var ret = $(document.createElement(el));
+		if (clazz) ret.addClass(clazz);
+		return ret;
+	}
+
+	var _entry = function() {
+		var sel = _el('select', 'typ');
+		for(var i in TYPES) {
+			sel.append( _el('option').text( TYPES[i] ) );
+		}
+		return _el('span', 'propeditor_entry')
+			.append( _el('input', 'key') )
+			.append( _el('span').text(' = '))
+			.append( _el('input', 'val') )
+			.append( sel );
+	}
+
+	var _check_entry = function(e, validator) {
+		var k = e.find('.key').removeClass('ui-state-error');
+		var v = e.find('.val').removeClass('ui-state-error');
+		var t = e.find('.typ').val();
+		var ok = _check_field(k);
+		ok = _check_field(v) && ok;
+		ok = ok && _defaultPropertyValidator(k, v, t);
+		if (ok && typeof validator == 'function') {
+			ok = validator(k, v, t);
+		}
+		if (ok) {
+			return [
+				{ 'name' : 'key', 'value' : k.val() },
+				{ 'name' : 'val', 'value' : v.val() },
+				{ 'name' : 'type', 'value' : t }
+			];
+			/*
+			return {
+				'key': k.val(),
+				'val': v.val(),
+				'type': t
+			}*/
+		}
+		return false;
+	}
+
+	var _check_field = function(f) {
+		if (!f.val()) {
+			f.addClass('ui-state-error');
+			return false;
+		}
+		return true;
+	}
+
+	var _range = function(field, isint, min, max) {
+		var v = false;
+		if (isint) {
+			var v = parseInt(field.val());
+			var xv = parseFloat(field.val());
+			if ( isNaN(v) || isNaN(xv) || xv != v) return false;  // field is actually double
+		} else { // double
+			v = parseFloat(field.val());
+			if (isNaN(v)) return false;
+		}
+
+		return v >= min && v <= max;
+	}
+	
+	// key == element, value == element, type == type string
+	var _defaultPropertyValidator = function(key, value, type) {
+		var v = value.val();
+		var ok = true;
+		switch(type) {
+			case 'byte':
+				ok = _range(value, true, -128, 127);
+				break;
+			case 'int':
+				ok = _range(value, true, -2147483648, 2147483647);
+				break;
+			case 'long':
+				ok = _range(value, true, -9223372036854775808, 9223372036854775807);
+				break;
+			case 'float':
+				ok = _range(value, false, 1.4E-45, 3.4E38);
+				break;
+			case 'double':
+				ok = _range(value, false, 4.9E-324, 1.7E308);
+				break;
+			case 'char':
+				ok = v.length == 1;
+				break;
+		}
+		if (!ok) value.addClass('ui-state-error');
+		return ok;
+	}
+
+})( jQuery );
\ No newline at end of file

Propchange: felix/trunk/webconsole-plugins/event/src/main/resources/res/ui/propeditor.js
------------------------------------------------------------------------------
    svn:mime-type = text/plain



Mime
View raw message