Index: /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/action/SystemAction.java
===================================================================
--- /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/action/SystemAction.java	(revision 25579)
+++ /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/action/SystemAction.java	(revision 25580)
@@ -74,7 +74,22 @@
 			system.setAttribute(GSXML.SYSTEM_SUBSET_ATT, info);
 		}
-		else if (subaction.equals("ping")){
-			// No pinging on collections yet in GS3 as is there in GS2
-			// The ping subaction is at present just for activate.pl
+		else if (subaction.equals("ping")) { // can ping the server or a collection
+			String name = (String) params.get(GSParams.SYSTEM_MODULE_NAME);
+			
+			if(name != null && !name.equals("")) { 
+				// Pinging a collection (or module) with ?a=s&sa=ping&st=collection&sn=<colName>
+				// is a collection-level (servicecluster/module level) ping
+				
+				String type = (String) params.get(GSParams.SYSTEM_MODULE_TYPE);
+				if(type == null || type.equals("")) { 
+					type = "collection"; // if the st=collection was omitted, assume collection
+				}				
+				// ping action set to moduleType=Collection and moduleName=colName
+				system.setAttribute(GSXML.SYSTEM_MODULE_NAME_ATT, name);
+				system.setAttribute(GSXML.SYSTEM_MODULE_TYPE_ATT, type);
+				system.setAttribute(GSXML.TYPE_ATT, GSXML.SYSTEM_TYPE_PING);
+			} // else SYSTEM_MODULE_NAME given by the "sn" GSParam is null or empty 
+			  // meaning server-level ping: ?a=s&sa=ping
+			  
 			system.setAttribute(GSXML.TYPE_ATT, GSXML.SYSTEM_TYPE_PING);
 		}
Index: /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/core/MessageRouter.java
===================================================================
--- /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/core/MessageRouter.java	(revision 25579)
+++ /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/core/MessageRouter.java	(revision 25580)
@@ -570,4 +570,13 @@
   }
   
+  // testing whether a collection (or more generally, a module) is active
+  protected boolean pingModule(String name) {
+	// module (including collection) would have been added to module_map 
+	// if activated, and removed from map if deactivated.
+	// The this.collection_list Element would contain the collection too, 
+	// but the following check seems to be more generally useful
+	return this.module_map.containsKey(name);	
+  }
+  
   /** creates and configures a new collection
       if this is done for a reconfigure, the collection should be deactivated first.
@@ -835,5 +844,5 @@
     return false;
   }
-  
+    
   protected boolean deactivateModule(String type, String name) {
     
@@ -974,9 +983,24 @@
         Element elem = (Element)commands.item(i);
         String action = elem.getAttribute(GSXML.TYPE_ATT);
-		if (action.equals(GSXML.SYSTEM_TYPE_PING)) {
-			Element s = GSXML.createTextElement(this.doc, GSXML.STATUS_ELEM,  "Ping succeeded.");
+		
+		if (action.equals(GSXML.SYSTEM_TYPE_PING)) { // ?a=s&sa=ping or ?a=s&sa=ping(&st=collection)&sn=colname
+						
+			String message = ""; // will be creating the same messages as in GS2's recept/pingaction.cpp
+			String module_name = elem.getAttribute(GSXML.SYSTEM_MODULE_NAME_ATT);
+			String module_type = elem.getAttribute(GSXML.SYSTEM_MODULE_TYPE_ATT);			
+			
+			if(module_name.equals("")) { // server-level ping				
+				message = "Ping succeeded.";
+			} else { // ping at collection level
+				if(pingModule(module_name)) {					
+					message = "Ping for " + module_name + " succeeded.";
+				} else {
+					message = "Ping for " + module_name + " did not succeed.";
+				}
+			}
+			Element s = GSXML.createTextElement(this.doc, GSXML.STATUS_ELEM, message);
 			response.appendChild(s);
 		}
-		//if (action.equals(GSXML.SYSTEM_TYPE_ISPERSISTENT)) {
+		//else if (action.equals(GSXML.SYSTEM_TYPE_ISPERSISTENT)) {
 		//	Element s = GSXML.createTextElement(this.doc, GSXML.STATUS_ELEM,  "Persistent: true.");
 		//	response.appendChild(s);
