package org.knopflerfish.bundle.soap.remotefw.client;
import org.osgi.framework.*;
import org.osgi.util.tracker.*;
import java.util.*;
import org.knopflerfish.service.log.LogRef;
import org.osgi.service.startlevel.*;
import org.knopflerfish.service.soap.remotefw.*;
import javax.xml.namespace.QName;
// Axis imports
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import java.net.*;
import java.lang.reflect.*;
import java.io.*;
import org.knopflerfish.util.*;
public class RemoteFWClient implements RemoteFW {
boolean bDebug = "true".equals(System.getProperty("org.knopflerfish.soap.remotefw.client.debug", "false"));
String endpoint = null;
Service service = null;
Call call = null;
BundleContextImpl remoteBC = null;
Map caches = new HashMap();
public RemoteFWClient() {
CacheMap fastCache = new CacheMap(1000);
CacheMap slowCache = new CacheMap(10000);
caches.put("getStartLevel", fastCache);
caches.put("getBundleStartLevel", fastCache);
caches.put("getInitialBundleStartLevel", fastCache);
caches.put("isBundlePersistentlyStarted", fastCache);
caches.put("isBundleActivationPolicyUsed", fastCache);
caches.put("getBundle", fastCache);
caches.put("getBundles", slowCache);
caches.put("getBundleLocation", slowCache);
caches.put("getBundleState", slowCache);
caches.put("getBundleManifest", slowCache);
caches.put("getRegisteredServices", fastCache);
caches.put("getServicesInUse", fastCache);
caches.put("getServiceReferences", fastCache);
caches.put("getServiceReferences2", fastCache);
caches.put("getServiceProperties", slowCache);
caches.put("getSystemProperties", slowCache);
caches.put("getServiceEvents", fastCache);
caches.put("getFrameworkEvents", slowCache);
caches.put("getBundleEvents", fastCache);
caches.put("getStartLevel", slowCache);
caches.put("getBundleStartLevel", slowCache);
caches.put("getExportedPackage", slowCache);
caches.put("getExportedPackages", slowCache);
}
void open(String host) throws Exception {
endpoint = host + "/axis/services/OSGiFramework";
service = new Service();
call = (Call) service.createCall();
call.setTargetEndpointAddress( new URL(endpoint) );
System.out.println("opened " + endpoint +
", bundles=" + doCall("getBundles"));
remoteBC = new BundleContextImpl(this);
remoteBC.start();
}
public void close() {
if(remoteBC != null) {
remoteBC.stop();
remoteBC = null;
}
endpoint = null;
service = null;
call = null;
}
void flushCache() {
synchronized(callLock) {
for(Iterator it = caches.keySet().iterator(); it.hasNext(); ) {
String opName = (String)it.next();
CacheMap cache = (CacheMap)caches.get(opName);
cache.clear();
}
}
}
public BundleContext getBundleContext() {
return remoteBC;
}
public void startBundle(long bid) {
doCall("startBundle", bid);
flushCache();
}
public void stopBundle(long bid) {
doCall("stopBundle", bid);
flushCache();
}
public void updateBundle(long bid) {
doCall("updateBundle", bid);
flushCache();
}
public void uninstallBundle(long bid) {
doCall("uninstallBundle", bid);
flushCache();
}
public long installBundle(String location) {
Long bid = (Long)doCall("installBundle", location);
flushCache();
return bid.longValue();
}
public long getBundle() {
return ((Long)doCall("getBundle")).longValue();
}
public long[] getBundles() {
return toLongArray(doCall("getBundles"));
}
public String getBundleContextProperty(String key) {
String v = (String)doCall("getBundleContextProperty",
new Object[] { key });
return NULL_STR.equals(v) ? null : v;
}
public String getBundleLocation(long bid) {
return (String)doCall("getBundleLocation", bid);
}
public int getBundleState(long bid) {
return ((Integer)doCall("getBundleState", bid)).intValue();
}
public long[] getServicesInUse(long bid) {
return toLongArray(doCall("getServicesInUse", bid));
}
public long[] getRegisteredServices(long bid) {
return toLongArray(doCall("getRegisteredServices", bid));
}
public long[] getServiceReferences(String filter) {
return getServiceReferences2(null, filter);
}
public long[] getServiceReferences2(String clazz, String filter) {
return toLongArray(doCall("getServiceReferences2",
new Object[] {
clazz == null ? NULL_STR : clazz,
filter == null ? NULL_STR : filter
}));
}
public Map getBundleManifest(long bid) {
return (Map)doCall("getBundleManifest", bid);
}
public long[] getServices() {
return toLongArray(doCall("getServices"));
}
public long[] getFrameworkEvents() {
return toLongArray(doCall("getFrameworkEvents"));
}
public long[] getBundleEvents() {
return toLongArray(doCall("getBundleEvents"));
}
public long[] getServiceEvents() {
return toLongArray(doCall("getServiceEvents"));
}
public Map getServiceProperties(long sid) {
return (Map)doCall("getServiceProperties", sid);
}
public int getStartLevel() {
return ((Integer)doCall("getStartLevel")).intValue();
}
public void setStartLevel(int level) {
doCall("setStartLevel", level);
}
public void setBundleStartLevel(long bid, int level) {
doCall("setBundleStartLevel", new Object[] { new Long(bid),
new Integer(level)});
}
public int getBundleStartLevel(long bid) {
return ((Integer)doCall("getBundleStartLevel", bid)).intValue();
}
public void setInitialBundleStartLevel(int level){
doCall("setInitialBundleStartLevel", level);
}
public int getInitialBundleStartLevel() {
return ((Integer)doCall("getInitialBundleStartLevel")).intValue();
}
public boolean isBundlePersistentlyStarted(long bid) {
return ((Boolean)doCall("isBundlePersistentlyStarted", bid)).booleanValue();
}
public boolean isBundleActivationPolicyUsed(long bid) {
return ((Boolean)doCall("isBundleActivationPolicyUsed", bid)).booleanValue();
}
public Map getExportedPackage(String name) {
return (Map)doCall("getExportedPackage", name);
}
public Map[] getExportedPackages(long bid) {
return (Map[])doCall("getExportedPackages", bid);
}
public void refreshPackages(long[] bids) {
if(bids == null) {
doCall("refreshPackages", new long[0]);
} else {
doCall("refreshPackages", bids);
}
}
public Map getSystemProperties() {
return (Map)doCall("getSystemProperties");
}
Object doCall(String opName) {
return doCall(opName, new Object[0]);
}
Object doCall(String opName, long val) {
return doCall(opName, new Object[] { new Long(val) });
}
Object doCall(String opName, int val) {
return doCall(opName, new Object[] { new Integer(val) });
}
Object doCall(String opName, Object val) {
return doCall(opName, new Object[] { val });
}
Object callLock = new Object();
Object doCall(String opName, Object[] params) {
synchronized(callLock) {
String cacheKey = null;
Map cache = (Map)caches.get(opName);
if(cache != null) {
cacheKey = opName + ":" + toDisplay(params);
Object cacheResult = cache.get(cacheKey);
if(cacheResult != null) {
if(bDebug) {
System.out.println("cached " + opName +
"(" + toDisplay(params) + ")");
}
return cacheResult;
}
}
try {
call.setOperationName(new QName(opName));
if(bDebug) {
System.out.println("doCall " + opName +
"(" + toDisplay(params) + ")");
}
Object r = call.invoke(params);
if(cache != null) {
cache.put(cacheKey, r);
}
return r;
} catch (Exception e) {
e.printStackTrace();
throw new NestedRuntimeException("Failed to call " + opName + ": ", e);
}
}
}
static long[] toLongArray(Object obj) {
if(obj == null) {
return null;
}
long[] la = new long[Array.getLength(obj)];
for(int i = 0; i < la.length; i++) {
la[i] = ((Long)Array.get(obj, i)).longValue();
}
return la;
}
public static Object toDisplay(Object val) {
if(val != null) {
if(NULL_STR.equals(val)) {
return "null";
}
if(val instanceof String) {
return "\"" + val + "\"";
}
if(val.getClass().isArray()) {
StringBuffer sb = new StringBuffer();
sb.append("[");
for(int i = 0; i < Array.getLength(val); i++) {
sb.append(toDisplay(Array.get(val, i)));
if(i < Array.getLength(val) - 1) {
sb.append(",");
}
}
sb.append("]");
return sb.toString();
}
}
return val;
}
}
class NestedRuntimeException extends RuntimeException {
Throwable nested;
public NestedRuntimeException(String msg, Throwable t) {
super(msg);
this.nested = nested;
}
public String getMessage() {
StringBuffer sb = new StringBuffer();
sb.append(super.getMessage());
if(nested != null) {
StringWriter sw = new StringWriter();
nested.printStackTrace(new PrintWriter(sw));
sb.append(", Nested exception:\n" + sw.toString());
}
return sb.toString();
}
public String toString() {
return getClass().toString() + ": " + getMessage();
}
}