/* * Copyright (c) 2003-2004, KNOPFLERFISH project * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following * conditions are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * - Neither the name of the KNOPFLERFISH project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.knopflerfish.bundle.soap.remotefw.client; import java.io.*; import java.lang.reflect.*; import java.net.*; import java.util.*; import org.osgi.framework.*; import org.osgi.service.startlevel.*; import org.osgi.util.tracker.*; import org.knopflerfish.service.log.LogRef; import org.knopflerfish.service.soap.remotefw.*; import org.knopflerfish.bundle.soap.remotefw.*; import org.knopflerfish.util.*; import org.ksoap2.SoapEnvelope; import org.ksoap2.serialization.SoapObject; import org.ksoap2.serialization.SoapPrimitive; import org.ksoap2.serialization.SoapSerializationEnvelope; import org.ksoap2.transport.HttpTransportSE; public class RemoteFWClient implements RemoteFW { boolean bDebug = "true".equals(System.getProperty("org.knopflerfish.soap.remotefw.client.debug", "false")); String endpoint = null; HttpTransportSE httpTransport = null; SoapSerializationEnvelope soapEnvelope = 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("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("getUsingBundles", slowCache); 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 + "/soap/services/OSGiFramework"; httpTransport = new HttpTransportSE(endpoint); soapEnvelope = new SoapSerializationEnvelope(SoapEnvelope.VER10); httpTransport.debug = true; SoapObject rpc = new SoapObject("http://www.w3.org/2001/12/soap-envelope", "getBundles"); soapEnvelope.env = "http://www.w3.org/2001/12/soap-envelope"; soapEnvelope.bodyOut = rpc; httpTransport.call("getBundles", soapEnvelope); remoteBC = new BundleContextImpl(this); remoteBC.start(); } public void close() { if(remoteBC != null) { remoteBC.stop(); remoteBC = null; } endpoint = 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) { String location = getBundleLocation(bid); if (location.startsWith(Util.LOC_PROT)) { try { String data = encodeFile(location.substring(Util.LOC_PROT.length())); doCall("updateBundle", new Object[] { new Long(bid), data }); } catch (IOException e) { Activator.log.warn("Failed to encode bundle for update", e); throw new NestedRuntimeException("Failed to encode bundle for update", e); } } else { doCall("updateBundle", bid); } flushCache(); } public void uninstallBundle(long bid) { doCall("uninstallBundle", bid); flushCache(); } public long installBundle(String location) { try { if (location.startsWith(Util.FILE_PROT) && !"true".equals(System.getProperty("org.knopflerfish.soap.remotefw.client.sendlocalpaths", "false"))) { location = encodeFile(location); } } catch (IOException e) { Activator.log.warn("Failed to call installBundle(file:...): ", e); throw new NestedRuntimeException("Failed to call installBundle(file:...): ", e); } Object obj = doCall("installBundle", location); Long bid = new Long(obj == null ? "0" : obj.toString()); flushCache(); return bid.longValue(); } private String encodeFile(String location) throws IOException { FileInputStream in = new FileInputStream(location.substring("file:".length())); int i; ByteArrayOutputStream out = new ByteArrayOutputStream(); while ((i = in.read()) != -1) { out.write(i); } return "B64(" + location + "):" + Base64.encode(out.toByteArray()); } public long getBundle() { Object obj = doCall("getBundle"); return (obj == null ? 0 : new Long(obj.toString()).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 toString(doCall("getBundleLocation", bid)); } public int getBundleState(long bid) { Object obj = doCall("getBundleState", bid); return (obj == null ? 0 : new Integer(obj.toString()).intValue()); } public long[] getUsingBundles(long sid) { return toLongArray(doCall("getUsingBundles", sid)); } 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 Vector getBundleManifest(long bid) { Object obj = doCall("getBundleManifest", bid); if (obj instanceof Vector) { return (Vector) obj; } else if (obj instanceof SoapObject) { return soapObjectToVector((SoapObject) obj); } else { throw new RuntimeException("getBundleManifest returned something strange: " + obj + " (" + obj.getClass().getName() + ")"); } } 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 Vector getServiceProperties(long sid) { Object obj = doCall("getServiceProperties", sid); if (obj instanceof Vector) { return (Vector) obj; } else if (obj instanceof SoapObject) { return soapObjectToVector((SoapObject) obj); } else { throw new RuntimeException("getServiceProperties returned something strange: " + obj + " (" + obj.getClass().getName() + ")"); } } private Vector soapObjectToVector(SoapObject sobj) { Vector vector = new Vector(); for (int i = 0; i < sobj.getPropertyCount(); i++) { Object obj = sobj.getProperty(i); if (obj instanceof SoapObject) { obj = soapObjectToVector((SoapObject) obj); } vector.addElement(obj); } return vector; } public int getStartLevel() { Object obj = doCall("getStartLevel"); return (obj == null ? 0 : new Integer(obj.toString()).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) { Object obj = doCall("getBundleStartLevel", bid); return (obj == null ? 0 : new Integer(obj.toString()).intValue()); } public void setInitialBundleStartLevel(int level){ doCall("setInitialBundleStartLevel", level); } public int getInitialBundleStartLevel() { Object obj = doCall("getInitialBundleStartLevel"); return (obj == null ? 0 : new Integer(obj.toString()).intValue()); } public boolean isBundlePersistentlyStarted(long bid) { return new Boolean(doCall("isBundlePersistentlyStarted", bid).toString()).booleanValue(); } public Vector getExportedPackage(String name) { Object obj = doCall("getExportedPackage", name); if (obj instanceof Vector) { return (Vector) obj; } else if (obj instanceof SoapObject) { return soapObjectToVector((SoapObject) obj); } else { throw new RuntimeException("getExportedPackage returned something strange: " + obj + " (" + obj.getClass().getName() + ")"); } } public Vector getExportedPackages(long bid) { Object obj = doCall("getExportedPackages", bid); if (obj instanceof Vector) { return (Vector) obj; } else if (obj instanceof SoapObject) { return soapObjectToVector((SoapObject) obj); } else { throw new RuntimeException("getExportedPackages returned something strange: " + obj + " (" + obj.getClass().getName() + ")"); } } public void refreshPackages(long[] bids) { if(bids == null) { doCall("refreshPackages", new long[0]); } else { doCall("refreshPackages", bids); } } public Vector getSystemProperties() { Object obj = doCall("getSystemProperties"); if (obj instanceof Vector) { return (Vector) obj; } else if (obj instanceof SoapObject) { return soapObjectToVector((SoapObject) obj); } else { throw new RuntimeException("getSystemProperties returned something strange: " + obj + " (" + obj.getClass().getName() + ")"); } } public Vector getFullLog() { Object obj = doCall("getFullLog"); return getLog(obj); } public Vector getLog() { Object obj = doCall("getLog"); return getLog(obj); } private Vector getLog(Object obj) { Vector vector; if (obj instanceof Vector) { vector = (Vector) obj; } else if (obj instanceof SoapObject) { vector = soapObjectToVector((SoapObject) obj); } else { throw new RuntimeException("getSystemProperties returned something strange: " + obj + " (" + obj.getClass().getName() + ")"); } Vector result = new Vector(); for (int i=0; i 1) { e = new LogThrowableImpl(vector.elementAt(i++).toString(), vector.elementAt(i++).toString(), vector.elementAt(i++).toString()); } else { i += 3; } result.addElement(new LogEntryImpl(this, bundle, level, message, time, e)); } return result; } public void createSession(String name) { doCall("createSession", name); } public void abortCommand() { doCall("abortCommand"); } public void closeSession() { doCall("closeSession"); } public void setEscapeChar(char ch) { doCall("setEscapeChar", new Character(ch)); } public void setInterruptString(String str) { doCall("setInterruptString", str); } public String[] setAlias(String key, String[] val) { Vector vector = new Vector(); vector.addElement(key); for (int i=0; i