Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarkus Alexander Kuppe2013-11-01 12:34:50 +0000
committerMarkus Alexander Kuppe2013-11-06 08:33:26 +0000
commit573f554d696f8fe5f9fe435ace79e8d2b29bde5c (patch)
treefbb40ef40c1285de86a9422e9d916f27ef3ac6c5
parentac5fa5c492fad225d4708bf29aa18292b4738ebb (diff)
downloadorg.eclipse.ecf-573f554d696f8fe5f9fe435ace79e8d2b29bde5c.tar.gz
org.eclipse.ecf-573f554d696f8fe5f9fe435ace79e8d2b29bde5c.tar.xz
org.eclipse.ecf-573f554d696f8fe5f9fe435ace79e8d2b29bde5c.zip
Bug 420858 - [r-OSGi] Sync SF.net and ECF's codebase
https://bugs.eclipse.org/420858 Syncs to SF.net revision "r1317" (2011-02-14 16:41:38 +0100 (Mon, 14 Feb 2011))
-rw-r--r--protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/RemoteOSGiService.java16
-rw-r--r--protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/ChannelEndpointImpl.java328
-rw-r--r--protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/ChannelEndpointMultiplexer.java6
-rw-r--r--protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/CodeAnalyzer.java37
-rw-r--r--protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/ProxyGenerator.java55
-rw-r--r--protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/RemoteOSGiActivator.java56
-rw-r--r--protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/RemoteOSGiServiceImpl.java159
-rw-r--r--protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/RemoteServiceReferenceImpl.java14
-rw-r--r--protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/RemoteServiceRegistration.java65
-rw-r--r--protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/TCPChannelFactory.java40
-rw-r--r--protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/messages/DeliverServiceMessage.java1
-rw-r--r--protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/messages/RemoteOSGiMessage.java2
-rw-r--r--protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/util/SmartObjectInputStream.java271
-rw-r--r--protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/util/SmartObjectOutputStream.java303
-rw-r--r--protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/util/SmartObjectStreamClass.java150
-rw-r--r--protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/util/StringUtils.java136
16 files changed, 846 insertions, 793 deletions
diff --git a/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/RemoteOSGiService.java b/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/RemoteOSGiService.java
index d38feefdb..4393356ed 100644
--- a/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/RemoteOSGiService.java
+++ b/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/RemoteOSGiService.java
@@ -29,6 +29,7 @@
package ch.ethz.iks.r_osgi;
import java.io.IOException;
+import java.lang.reflect.Method;
import org.osgi.framework.Filter;
@@ -254,6 +255,21 @@ public interface RemoteOSGiService {
final Object[] args, final AsyncRemoteCallCallback callback);
/**
+ * make an asynchronous remote call to a service
+ *
+ * @param service
+ * the URI of the service
+ * @param method
+ * the method to call
+ * @param args
+ * the arguments to pass
+ * @param callback
+ * a callback to be called when the result is available
+ */
+ void asyncRemoteCall(final URI service, final Method method,
+ final Object[] args, final AsyncRemoteCallCallback callback);
+
+ /**
* get the port on which the corresponding NetworkChannelFactory for the
* given protocol listens for incoming connections.
*
diff --git a/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/ChannelEndpointImpl.java b/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/ChannelEndpointImpl.java
index 85acd857e..37056fdea 100644
--- a/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/ChannelEndpointImpl.java
+++ b/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/ChannelEndpointImpl.java
@@ -39,16 +39,12 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Dictionary;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
-import java.util.Set;
-import java.util.StringTokenizer;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleException;
-import org.osgi.framework.Constants;
import org.osgi.framework.Filter;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.event.Event;
@@ -84,7 +80,7 @@ import ch.ethz.iks.r_osgi.streams.InputStreamHandle;
import ch.ethz.iks.r_osgi.streams.InputStreamProxy;
import ch.ethz.iks.r_osgi.streams.OutputStreamHandle;
import ch.ethz.iks.r_osgi.streams.OutputStreamProxy;
-import ch.ethz.iks.util.CollectionUtils;
+import ch.ethz.iks.r_osgi.types.BoxedPrimitive;
/**
* <p>
@@ -117,6 +113,8 @@ public final class ChannelEndpointImpl implements ChannelEndpoint {
int usageCounter = 1;
+ private static final boolean USE_THREAD_POOL = true;
+
/**
* the channel.
*/
@@ -184,13 +182,10 @@ public final class ChannelEndpointImpl implements ChannelEndpoint {
* filter for events to prevent loops in the remote delivery if the peers
* connected by this channel have non-disjoint topic spaces.
*/
- private static final String NO_LOOPS = "(&(!(" //$NON-NLS-1$
- + RemoteEventMessage.EVENT_SENDER_URI + "=*))" //$NON-NLS-1$
- // [TCK][r-OSGi] NonSerializableException when running remoteserviceadmin ct
- // https://bugs.eclipse.org/418740
- + "(!(" + EventConstants.EVENT_TOPIC
- + "=org/osgi/service/remoteserviceadmin/*))" //$NON-NLS-1$
- + ")"; //$NON-NLS-1$
+ private static final String NO_LOOPS = "(!(" //$NON-NLS-1$
+ + RemoteEventMessage.EVENT_SENDER_URI + "=*))"; //$NON-NLS-1$
+
+ private ThreadGroup threadPool;
private ArrayList workQueue = new ArrayList();
@@ -215,11 +210,13 @@ public final class ChannelEndpointImpl implements ChannelEndpoint {
ChannelEndpointImpl(final NetworkChannelFactory factory,
final URI endpointAddress) throws RemoteOSGiException, IOException {
networkChannel = factory.getConnection(this, endpointAddress);
- if (RemoteOSGiServiceImpl.DEBUG) {
+ if (RemoteOSGiServiceImpl.DEBUG && RemoteOSGiServiceImpl.log != null) {
RemoteOSGiServiceImpl.log.log(LogService.LOG_DEBUG,
"opening new channel " + getRemoteAddress()); //$NON-NLS-1$
}
- initThreadPool();
+ if (USE_THREAD_POOL) {
+ initThreadPool();
+ }
RemoteOSGiServiceImpl.registerChannelEndpoint(this);
}
@@ -232,7 +229,9 @@ public final class ChannelEndpointImpl implements ChannelEndpoint {
ChannelEndpointImpl(final NetworkChannel channel) {
networkChannel = channel;
channel.bind(this);
- initThreadPool();
+ if (USE_THREAD_POOL) {
+ initThreadPool();
+ }
RemoteOSGiServiceImpl.registerChannelEndpoint(this);
}
@@ -241,33 +240,35 @@ public final class ChannelEndpointImpl implements ChannelEndpoint {
*/
private void initThreadPool() {
// TODO: tradeoff, could as well be central for all endpoints...
- final ThreadGroup threadPool = new ThreadGroup("WorkerThreads"
- + toString());
- for (int i = 0; i < RemoteOSGiServiceImpl.MAX_THREADS_PER_ENDPOINT; i++) {
- final Thread t = new Thread(threadPool, "r-OSGi ChannelWorkerThread" + i) {
- public void run() {
- try {
- while (!isInterrupted()) {
- final Runnable r;
- synchronized (workQueue) {
- while (workQueue.isEmpty()) {
- workQueue.wait();
+ // could also be instantiated lazily...
+ if (USE_THREAD_POOL) {
+ threadPool = new ThreadGroup("WorkerThreads" + toString());
+ for (int i = 0; i < RemoteOSGiServiceImpl.MAX_THREADS_PER_ENDPOINT; i++) {
+ final Thread t = new Thread(threadPool, "WorkerThread" + i) {
+ public void run() {
+ try {
+ while (!isInterrupted()) {
+ final Runnable r;
+ synchronized (workQueue) {
+ while (workQueue.isEmpty()) {
+ workQueue.wait();
+ }
+ r = (Runnable) workQueue.remove(0);
}
- r = (Runnable) workQueue.remove(0);
+ r.run();
}
- r.run();
+ } catch (final InterruptedException ie) {
+ // that's fine
}
- } catch (InterruptedException ie) {
- ie.printStackTrace();
}
- }
- };
- t.start();
+ };
+ t.start();
+ }
}
}
/**
- * process a recieved message. Called by the channel.
+ * process a received message. Called by the channel.
*
* @param msg
* the received message.
@@ -280,35 +281,47 @@ public final class ChannelEndpointImpl implements ChannelEndpoint {
return;
}
final Integer xid = new Integer(msg.getXID());
- final WaitingCallback callback;
+ final AsyncCallback callback;
synchronized (callbacks) {
- callback = (WaitingCallback) callbacks.remove(xid);
+ callback = (AsyncCallback) callbacks.remove(xid);
}
if (callback != null) {
callback.result(msg);
return;
} else {
- final Runnable r = new Runnable() {
- public void run() {
- final RemoteOSGiMessage reply = handleMessage(msg);
- if (reply != null) {
-
- try {
- networkChannel.sendMessage(reply);
- } catch (final NotSerializableException nse) {
- throw new RemoteOSGiException("Error sending " //$NON-NLS-1$
- + reply, nse);
- } catch (NullPointerException npe) {
- // channel got closed
- } catch (final IOException e) {
- dispose();
+ if (USE_THREAD_POOL) {
+ final Runnable r = new Runnable() {
+ public void run() {
+ final RemoteOSGiMessage reply = handleMessage(msg);
+ if (reply != null) {
+ try {
+ networkChannel.sendMessage(reply);
+ } catch (final NotSerializableException nse) {
+ throw new RemoteOSGiException("Error sending " //$NON-NLS-1$
+ + reply, nse);
+ } catch (final IOException e) {
+ dispose();
+ }
}
}
+ };
+ synchronized (workQueue) {
+ workQueue.add(r);
+ workQueue.notify();
+ }
+ } else {
+ final RemoteOSGiMessage reply = handleMessage(msg);
+ if (reply != null) {
+
+ try {
+ networkChannel.sendMessage(reply);
+ } catch (final NotSerializableException nse) {
+ throw new RemoteOSGiException("Error sending " //$NON-NLS-1$
+ + reply, nse);
+ } catch (final IOException e) {
+ dispose();
+ }
}
- };
- synchronized (workQueue) {
- workQueue.add(r);
- workQueue.notify();
}
}
}
@@ -438,7 +451,8 @@ public final class ChannelEndpointImpl implements ChannelEndpoint {
* @category ChannelEndpoint
*/
public Dictionary getProperties(final String serviceID) {
- return getRemoteReference(serviceID).getProperties();
+ final RemoteServiceReferenceImpl rref = getRemoteReference(serviceID);
+ return rref == null ? null : rref.getProperties();
}
/**
@@ -451,10 +465,14 @@ public final class ChannelEndpointImpl implements ChannelEndpoint {
* @category ChannelEndpoint
*/
public Dictionary getPresentationProperties(final String serviceID) {
+ final RemoteServiceReferenceImpl rref = getRemoteReference(serviceID);
+
final Dictionary attribs = new Hashtable();
attribs.put(RemoteOSGiService.SERVICE_URI, serviceID);
- attribs.put(RemoteOSGiService.PRESENTATION, getRemoteReference(
- serviceID).getProperty(RemoteOSGiService.PRESENTATION));
+ attribs.put(
+ RemoteOSGiService.PRESENTATION,
+ rref == null ? null : rref
+ .getProperty(RemoteOSGiService.PRESENTATION));
return attribs;
}
@@ -522,7 +540,7 @@ public final class ChannelEndpointImpl implements ChannelEndpoint {
return;
}
- if (RemoteOSGiServiceImpl.DEBUG) {
+ if (RemoteOSGiServiceImpl.DEBUG && RemoteOSGiServiceImpl.log != null) {
RemoteOSGiServiceImpl.log.log(LogService.LOG_DEBUG,
"DISPOSING ENDPOINT " + getRemoteAddress()); //$NON-NLS-1$
}
@@ -568,6 +586,21 @@ public final class ChannelEndpointImpl implements ChannelEndpoint {
}
}
+ // dispose off the thread pool
+ if (threadPool != null) {
+ final Thread[] threads = new Thread[RemoteOSGiServiceImpl.MAX_THREADS_PER_ENDPOINT];
+ final int count = threadPool.enumerate(threads);
+ for (int i = 0; i < count; i++) {
+ threads[i].interrupt();
+ try {
+ threads[i].join();
+ } catch (InterruptedException e) {
+ //
+ }
+ }
+ threadPool.destroy();
+ }
+
remoteServices = null;
remoteTopics = null;
timeOffset = null;
@@ -811,9 +844,11 @@ public final class ChannelEndpointImpl implements ChannelEndpoint {
final Bundle bundle = RemoteOSGiActivator.getActivator()
.getContext().installBundle(ref.getURI().toString(), in);
- retrieveDependencies((String) bundle.getHeaders().get(
- Constants.IMPORT_PACKAGE), (String) bundle.getHeaders()
- .get(Constants.EXPORT_PACKAGE));
+ /*
+ * retrieveDependencies((String) bundle.getHeaders().get(
+ * Constants.IMPORT_PACKAGE), (String) bundle.getHeaders()
+ * .get(Constants.EXPORT_PACKAGE));
+ */
if (isProxy) {
// store the bundle for state updates and cleanup
@@ -858,65 +893,6 @@ public final class ChannelEndpointImpl implements ChannelEndpoint {
}
/**
- * tokenize a package import/export string
- *
- * @param str
- * the string
- * @return the tokens
- */
- private String[] getTokens(final String str) {
- final ArrayList result = new ArrayList();
- final StringTokenizer tokenizer = new StringTokenizer(str, ",");
- while (tokenizer.hasMoreTokens()) {
- final String token = tokenizer.nextToken();
- final int pos;
- // TODO: handle versions for R4!
- final String pkg = (pos = token.indexOf(";")) > -1 ? token
- .substring(0, pos).trim() : token.trim();
- if (!RemoteOSGiServiceImpl.checkPackageImport(pkg)) {
- result.add(pkg);
- }
- }
-
- return (String[]) result.toArray(new String[result.size()]);
- }
-
- /**
- * get the missing dependencies from remote for a given bundle defined by
- * its declared package import and exports.
- *
- * @param importString
- * the declared package imports
- * @param exportString
- * the declared package exports
- */
- private void retrieveDependencies(final String importString,
- final String exportString) {
-
- final Set exports = new HashSet(Arrays.asList(getTokens(exportString)));
- final Set imports = new HashSet(Arrays.asList(getTokens(importString)));
-
- final String[] missing = (String[]) CollectionUtils.rightDifference(
- imports, exports).toArray(new String[0]);
-
- if (missing.length > 0) {
- final RequestDependenciesMessage req = new RequestDependenciesMessage();
- req.setPackages(missing);
- final DeliverBundlesMessage deps = (DeliverBundlesMessage) sendAndWait(req);
- final byte[][] depBytes = deps.getDependencies();
- for (int i = 0; i < depBytes.length; i++) {
- try {
- RemoteOSGiActivator.getActivator().getContext()
- .installBundle("r-osgi://dep/" + missing[i],
- new ByteArrayInputStream(depBytes[i]));
- } catch (BundleException be) {
- be.printStackTrace();
- }
- }
- }
- }
-
- /**
* get the remote reference for a given serviceID.
*
* @param serviceID
@@ -924,6 +900,9 @@ public final class ChannelEndpointImpl implements ChannelEndpoint {
* @return the remote service reference, or <code>null</code>.
*/
RemoteServiceReferenceImpl getRemoteReference(final String uri) {
+ if (remoteServices == null) {
+ throw new RemoteOSGiException("Channel is closed."); //$NON-NLS-1$
+ }
return (RemoteServiceReferenceImpl) remoteServices.get(uri);
}
@@ -1058,32 +1037,19 @@ public final class ChannelEndpointImpl implements ChannelEndpoint {
final String serviceID = suMsg.getServiceID();
final short stateUpdate = suMsg.getType();
- final String serviceURI = getRemoteAddress()
- .resolve("#" + serviceID).toString();
-
switch (stateUpdate) {
case LeaseUpdateMessage.TOPIC_UPDATE: {
- // There is an older r-OSGi version that incorrectly sends an ArrayList
- // (1.0.0.RC4_v20131016-1848)
- Object topicsAdded = suMsg.getPayload()[0];
- if (topicsAdded instanceof List) {
- topicsAdded = ((List) topicsAdded).toArray(new String[0]);
- }
- Object topicsRemoved = suMsg.getPayload()[1];
- if (topicsRemoved instanceof List) {
- topicsRemoved = ((List) topicsRemoved).toArray(new String[0]);
- }
- updateTopics((String[]) topicsAdded, (String[]) topicsRemoved);
+ updateTopics((String[]) suMsg.getPayload()[0],
+ (String[]) suMsg.getPayload()[1]);
return null;
}
case LeaseUpdateMessage.SERVICE_ADDED: {
- final Dictionary properties = (Dictionary) suMsg.getPayload()[1];
- sanitizeServiceProperties(properties, serviceURI);
final RemoteServiceReferenceImpl ref = new RemoteServiceReferenceImpl(
(String[]) suMsg.getPayload()[0], serviceID,
- properties, this);
+ (Dictionary) suMsg.getPayload()[1], this);
- remoteServices.put(serviceURI, ref);
+ remoteServices.put(getRemoteAddress().resolve("#" + serviceID) //$NON-NLS-1$
+ .toString(), ref);
RemoteOSGiServiceImpl
.notifyRemoteServiceListeners(new RemoteServiceEvent(
@@ -1092,23 +1058,16 @@ public final class ChannelEndpointImpl implements ChannelEndpoint {
return null;
}
case LeaseUpdateMessage.SERVICE_MODIFIED: {
- final Dictionary properties = (Dictionary) suMsg.getPayload()[1];
- sanitizeServiceProperties(properties, serviceURI);
+ final Dictionary newProps = (Dictionary) suMsg.getPayload()[1];
final ServiceRegistration reg = (ServiceRegistration) proxiedServices
.get(serviceID);
if (reg != null) {
- reg.setProperties(properties);
+ reg.setProperties(newProps);
}
- final RemoteServiceReferenceImpl ref = getRemoteReference(serviceURI); //$NON-NLS-1$
- // If r-OSGi receives a SERVICE_MODIFIED for service X before it
- // knows about X (SERVICE_ADDED), there is no point in updating
- // the local service instance. It will fail with an NPE anyway.
- // (see https://bugs.eclipse.org/420433)
- if (ref == null && reg == null) {
- return null;
- }
- ref.setProperties(properties);
+ final RemoteServiceReferenceImpl ref = getRemoteReference(getRemoteAddress()
+ .resolve("#" + serviceID).toString()); //$NON-NLS-1$
+ ref.setProperties(newProps);
RemoteOSGiServiceImpl
.notifyRemoteServiceListeners(new RemoteServiceEvent(
RemoteServiceEvent.MODIFIED, ref));
@@ -1119,7 +1078,8 @@ public final class ChannelEndpointImpl implements ChannelEndpoint {
return null;
}
final RemoteServiceReference ref = (RemoteServiceReference) remoteServices
- .remove(serviceURI);
+ .remove(getRemoteAddress().resolve("#" + serviceID) //$NON-NLS-1$
+ .toString());
if (ref != null) {
RemoteOSGiServiceImpl
.notifyRemoteServiceListeners(new RemoteServiceEvent(
@@ -1134,7 +1094,12 @@ public final class ChannelEndpointImpl implements ChannelEndpoint {
be.printStackTrace();
}
proxiedServices.remove(serviceID);
- remoteServices.remove(serviceURI); //$NON-NLS-1$
+ try {
+ remoteServices.remove(getRemoteAddress().resolve(
+ "#" + serviceID).toString()); //$NON-NLS-1$
+ } catch (final RemoteOSGiException r) {
+ // channel was already closed.
+ }
}
return null;
}
@@ -1173,16 +1138,24 @@ public final class ChannelEndpointImpl implements ChannelEndpoint {
// invoke method
try {
- Object result = method.invoke(serv.getServiceObject(),
- arguments);
+ if (!TCPChannelFactory.beSmart) {
+ if (arguments != null) {
+ for (int i = 0; i < arguments.length; i++) {
+ if (arguments[i] instanceof BoxedPrimitive) {
+ arguments[i] = ((BoxedPrimitive) arguments[i])
+ .getBoxed();
+ }
+ }
+ }
+ }
+ final Object result = method.invoke(
+ serv.getServiceObject(), arguments);
final RemoteCallResultMessage m = new RemoteCallResultMessage();
m.setXID(invMsg.getXID());
if (result instanceof InputStream) {
- m
- .setResult(getInputStreamPlaceholder((InputStream) result));
+ m.setResult(getInputStreamPlaceholder((InputStream) result));
} else if (result instanceof OutputStream) {
- m
- .setResult(getOutputStreamPlaceholder((OutputStream) result));
+ m.setResult(getOutputStreamPlaceholder((OutputStream) result));
} else {
m.setResult(result);
}
@@ -1430,12 +1403,8 @@ public final class ChannelEndpointImpl implements ChannelEndpoint {
final RemoteServiceReferenceImpl[] refs = new RemoteServiceReferenceImpl[serviceIDs.length];
for (short i = 0; i < serviceIDs.length; i++) {
- final String serviceID = serviceIDs[i];
- final String serviceURI = getRemoteAddress().resolve("#" + serviceID).toString();
- final Dictionary properties = serviceProperties[i];
- sanitizeServiceProperties(properties, serviceURI);
refs[i] = new RemoteServiceReferenceImpl(serviceInterfaces[i],
- serviceID, properties, this);
+ serviceIDs[i], serviceProperties[i], this);
remoteServices.put(refs[i].getURI().toString(), refs[i]);
RemoteOSGiServiceImpl
@@ -1446,18 +1415,6 @@ public final class ChannelEndpointImpl implements ChannelEndpoint {
return refs;
}
- private void sanitizeServiceProperties(
- final Dictionary properties, final String serviceURI) {
- // adjust the properties
- properties.put(RemoteOSGiService.SERVICE_URI, serviceURI);
- // remove the service PID, if set
- properties.remove(Constants.SERVICE_PID);
- // remove the R-OSGi registration property
- properties.remove(RemoteOSGiService.R_OSGi_REGISTRATION);
- // also remote the ECF registration property
- properties.remove("org.eclipse.ecf.serviceRegistrationRemote"); //$NON-NLS-1$
- }
-
/**
* perform a stream operation.
*
@@ -1494,14 +1451,7 @@ public final class ChannelEndpointImpl implements ChannelEndpoint {
final String[] topicsRemoved) {
if (handlerReg == null) {
- // Remote might send a
- // ch.ethz.iks.r_osgi.messages.LeaseUpdateMessage.TOPIC_UPDATE
- // message
- // (see
- // ch.ethz.iks.r_osgi.impl.RemoteOSGiServiceImpl.setupTrackers(...).new
- // ServiceTrackerCustomizer() {...}.removedService(ServiceReference,
- // Object)) with null as the topicsAdded list. Thus, ignore null.
- if (topicsAdded != null && topicsAdded.length > 0) {
+ if (topicsAdded.length > 0) {
// register handler
final Dictionary properties = new Hashtable();
properties.put(EventConstants.EVENT_TOPIC, topicsAdded);
@@ -1537,7 +1487,8 @@ public final class ChannelEndpointImpl implements ChannelEndpoint {
}
}
- if (RemoteOSGiServiceImpl.MSG_DEBUG) {
+ if (RemoteOSGiServiceImpl.MSG_DEBUG
+ && RemoteOSGiServiceImpl.log != null) {
RemoteOSGiServiceImpl.log.log(LogService.LOG_DEBUG,
"NEW REMOTE TOPIC SPACE for " + getRemoteAddress() + " is " //$NON-NLS-1$ //$NON-NLS-2$
+ remoteTopics);
@@ -1621,9 +1572,12 @@ public final class ChannelEndpointImpl implements ChannelEndpoint {
} else if (s[i] instanceof OutputStream) {
((OutputStream) s[i]).close();
} else {
- RemoteOSGiServiceImpl.log
- .log(LogService.LOG_WARNING,
- "Object in input streams map was not an instance of a stream."); //$NON-NLS-1$
+ if (RemoteOSGiServiceImpl.DEBUG
+ && RemoteOSGiServiceImpl.log != null) {
+ RemoteOSGiServiceImpl.log
+ .log(LogService.LOG_WARNING,
+ "Object in input streams map was not an instance of a stream."); //$NON-NLS-1$
+ }
}
}
} catch (final IOException e) {
diff --git a/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/ChannelEndpointMultiplexer.java b/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/ChannelEndpointMultiplexer.java
index 5425f5b47..4f6f772b1 100644
--- a/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/ChannelEndpointMultiplexer.java
+++ b/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/ChannelEndpointMultiplexer.java
@@ -146,7 +146,8 @@ final class ChannelEndpointMultiplexer implements ChannelEndpoint,
primary.untrackRegistration(serviceURI);
primary = next;
primary.trackRegistration(serviceURI, reg);
- if (RemoteOSGiServiceImpl.DEBUG) {
+ if (RemoteOSGiServiceImpl.DEBUG
+ && RemoteOSGiServiceImpl.log != null) {
RemoteOSGiServiceImpl.log.log(
LogService.LOG_INFO,
"DOING FAILOVER TO " //$NON-NLS-1$
@@ -173,7 +174,8 @@ final class ChannelEndpointMultiplexer implements ChannelEndpoint,
primary.untrackRegistration(serviceURI);
primary = next;
primary.trackRegistration(serviceURI, reg);
- if (RemoteOSGiServiceImpl.DEBUG) {
+ if (RemoteOSGiServiceImpl.DEBUG
+ && RemoteOSGiServiceImpl.log != null) {
RemoteOSGiServiceImpl.log
.log(
LogService.LOG_INFO,
diff --git a/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/CodeAnalyzer.java b/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/CodeAnalyzer.java
index 62dd55431..1519a8f20 100644
--- a/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/CodeAnalyzer.java
+++ b/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/CodeAnalyzer.java
@@ -75,6 +75,11 @@ final class CodeAnalyzer implements ClassVisitor {
private final ClassLoader loader;
/**
+ * the class loader of the smart proxy
+ */
+ private ClassLoader smartProxyLoader;
+
+ /**
* the closure list.
*/
private final ArrayList closure = new ArrayList();
@@ -131,7 +136,7 @@ final class CodeAnalyzer implements ClassVisitor {
this.loader = loader;
if (imports != null) {
- final String[] tokens = StringUtils.stringToArray(imports, ","); //$NON-NLS-1$
+ final String[] tokens = StringUtils.splitString(imports, ","); //$NON-NLS-1$
importsMap = new HashMap(tokens.length);
for (int i = 0; i < tokens.length; i++) {
final int pos = tokens[i].indexOf(";"); //$NON-NLS-1$
@@ -147,7 +152,7 @@ final class CodeAnalyzer implements ClassVisitor {
}
if (exports != null) {
- final String[] tokens = StringUtils.stringToArray(exports, ","); //$NON-NLS-1$
+ final String[] tokens = StringUtils.splitString(exports, ","); //$NON-NLS-1$
exportsMap = new HashMap(tokens.length);
for (int i = 0; i < tokens.length; i++) {
final int pos = tokens[i].indexOf(";"); //$NON-NLS-1$
@@ -190,6 +195,14 @@ final class CodeAnalyzer implements ClassVisitor {
if (smartProxy != null) {
closure.add(smartProxy);
+ try {
+ smartProxyLoader = Class.forName(smartProxy).getClassLoader();
+ } catch (final ClassNotFoundException c) {
+ smartProxyLoader = null;
+ }
+ if (smartProxyLoader == loader) {
+ smartProxyLoader = null;
+ }
}
if (presentation != null) {
closure.add(presentation);
@@ -197,7 +210,8 @@ final class CodeAnalyzer implements ClassVisitor {
if (explicitInjections != null) {
closure.addAll(Arrays.asList(explicitInjections));
}
-
+
+ // do the real work
while (!closure.isEmpty()) {
visit((String) closure.remove(0));
}
@@ -292,7 +306,24 @@ final class CodeAnalyzer implements ClassVisitor {
}
reader.accept(this, ClassReader.SKIP_DEBUG
+ ClassReader.SKIP_FRAMES);
+ return;
} catch (final IOException ioe) {
+ if (smartProxyLoader != null) {
+ try {
+ final ClassReader reader = new ClassReader(
+ smartProxyLoader.getResourceAsStream(classFile));
+
+ injections.put(classFile, reader.b);
+ if (exportsMap.containsKey(pkg)) {
+ proxyExports.add(pkg);
+ }
+ reader.accept(this, ClassReader.SKIP_DEBUG
+ + ClassReader.SKIP_FRAMES);
+ return;
+ } catch (final IOException ioe2) {
+ throw new ClassNotFoundException(className);
+ }
+ }
throw new ClassNotFoundException(className);
}
}
diff --git a/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/ProxyGenerator.java b/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/ProxyGenerator.java
index a7936092a..b4f2c4c14 100644
--- a/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/ProxyGenerator.java
+++ b/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/ProxyGenerator.java
@@ -30,6 +30,8 @@ package ch.ethz.iks.r_osgi.impl;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
@@ -56,6 +58,7 @@ import org.objectweb.asm.MethodAdapter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
+import org.osgi.framework.Constants;
import org.osgi.service.log.LogService;
import ch.ethz.iks.r_osgi.RemoteOSGiService;
@@ -219,20 +222,17 @@ class ProxyGenerator implements ClassVisitor, Opcodes {
final Attributes attr = mf.getMainAttributes();
attr.putValue("Manifest-Version", "1.0"); //$NON-NLS-1$ //$NON-NLS-2$
attr.putValue("Created-By", "R-OSGi Proxy Generator"); //$NON-NLS-1$ //$NON-NLS-2$
- attr.putValue("Bundle-Activator", className); //$NON-NLS-1$
- attr.putValue("Bundle-Classpath", "."); //$NON-NLS-1$ //$NON-NLS-2$
- attr.putValue("Bundle-SymbolicName", "R-OSGi Proxy Bundle generated for Endpoint " + uri.toString()); //$NON-NLS-1$ //$NON-NLS-2$
- attr
- .putValue(
- "Import-Package", //$NON-NLS-1$
- "org.osgi.framework, ch.ethz.iks.r_osgi, ch.ethz.iks.r_osgi.types, ch.ethz.iks.r_osgi.channels" //$NON-NLS-1$
- + ("".equals(deliv.getOptionalImports()) ? "" : ", " //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- + deliv.getOptionalImports())
- + ("".equals(deliv.getImports()) ? "" : ", ") //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- + deliv.getImports());
+ attr.putValue(Constants.BUNDLE_ACTIVATOR, className);
+ attr.putValue(Constants.BUNDLE_CLASSPATH, "."); //$NON-NLS-1$
+ attr.putValue(
+ Constants.IMPORT_PACKAGE,
+ "org.osgi.framework, ch.ethz.iks.r_osgi, ch.ethz.iks.r_osgi.types, ch.ethz.iks.r_osgi.channels" //$NON-NLS-1$
+ + ("".equals(deliv.getImports()) ? "" : ", ") //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ + deliv.getImports());
if (!"".equals(deliv.getExports())) { //$NON-NLS-1$
- attr.putValue("Export-Package", deliv.getExports()); //$NON-NLS-1$
+ attr.putValue(Constants.EXPORT_PACKAGE, deliv.getExports());
}
+ attr.putValue(Constants.BUNDLE_SYMBOLICNAME, "R-OSGi Proxy Bundle generated for Endpoint " + uri.toString()); //$NON-NLS-1$ //$NON-NLS-2$
final ByteArrayOutputStream bout = new ByteArrayOutputStream();
final JarOutputStream out = new JarOutputStream(bout, mf);
@@ -294,12 +294,14 @@ class ProxyGenerator implements ClassVisitor, Opcodes {
out.close();
if (RemoteOSGiServiceImpl.PROXY_DEBUG) {
- // final File file =
- // RemoteOSGiActivator.context.getDataFile(fileName
- // + "_" + sourceID + ".jar");
-
- // RemoteOSGiServiceImpl.log.log(LogService.LOG_DEBUG,
- // "Created Proxy Bundle " + file);
+ final File file = RemoteOSGiActivator.getActivator().getContext()
+ .getDataFile("bundle_" + sourceID + ".jar");
+
+ final FileOutputStream fout = new FileOutputStream(file);
+ fout.write(bout.toByteArray());
+ fout.close();
+ System.err.println("Wrote proxy bundle to "
+ + file.getAbsolutePath());
}
return new ByteArrayInputStream(bout.toByteArray());
@@ -384,7 +386,7 @@ class ProxyGenerator implements ClassVisitor, Opcodes {
// like java.io.Serializable (or other classes
// provided by the JRE).
// (see https://bugs.eclipse.org/420112)
- classLoader = getClass().getClassLoader();
+ classLoader = ClassLoader.getSystemClassLoader();
}
reader = new ClassReader(classLoader.getResourceAsStream(
superIface + ".class")); //$NON-NLS-1$
@@ -433,7 +435,8 @@ class ProxyGenerator implements ClassVisitor, Opcodes {
|| (smartProxyClassName == null && name
.equals(serviceInterfaceNames[0].replace('.', '/')))) {
- if (RemoteOSGiServiceImpl.PROXY_DEBUG) {
+ if (RemoteOSGiServiceImpl.PROXY_DEBUG
+ && RemoteOSGiServiceImpl.log != null) {
RemoteOSGiServiceImpl.log.log(LogService.LOG_DEBUG,
"creating proxy class " + implName); //$NON-NLS-1$
}
@@ -467,13 +470,11 @@ class ProxyGenerator implements ClassVisitor, Opcodes {
} else {
// we have an interface
- writer
- .visit(
- (version >= V1_5 && RemoteOSGiServiceImpl.IS_JAVA5) ? V1_5
- : V1_2, ACC_PUBLIC + ACC_SUPER,
- implName, null,
- "java/lang/Object", serviceInterfaces); //$NON-NLS-1$
- if (RemoteOSGiServiceImpl.PROXY_DEBUG) {
+ writer.visit(
+ (version >= V1_5 && RemoteOSGiServiceImpl.IS_JAVA5) ? V1_5
+ : V1_2, ACC_PUBLIC + ACC_SUPER, implName, null,
+ "java/lang/Object", serviceInterfaces); //$NON-NLS-1$
+ if (RemoteOSGiServiceImpl.PROXY_DEBUG && RemoteOSGiServiceImpl.log != null) {
RemoteOSGiServiceImpl.log.log(LogService.LOG_DEBUG,
"Creating Proxy Bundle from Interfaces " //$NON-NLS-1$
+ Arrays.asList(serviceInterfaceNames));
diff --git a/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/RemoteOSGiActivator.java b/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/RemoteOSGiActivator.java
index fcfdc9f32..e06b9c084 100644
--- a/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/RemoteOSGiActivator.java
+++ b/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/RemoteOSGiActivator.java
@@ -1,4 +1,4 @@
-/* Copyright (c) 2006-2009 Jan S. Rellermeyer
+/* Copyright (c) 2006-2010 Jan S. Rellermeyer
* Systems Group,
* Department of Computer Science, ETH Zurich.
* All rights reserved.
@@ -33,9 +33,7 @@ import java.util.Hashtable;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-import org.osgi.service.log.LogService;
-
+import org.osgi.framework.BundleException;
import ch.ethz.iks.r_osgi.RemoteOSGiService;
import ch.ethz.iks.r_osgi.Remoting;
import ch.ethz.iks.r_osgi.channels.NetworkChannelFactory;
@@ -75,35 +73,35 @@ public final class RemoteOSGiActivator implements BundleActivator {
* @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
*/
public void start(final BundleContext context) throws Exception {
- instance = this;
- this.context = context;
+ try {
+ instance = this;
+ this.context = context;
- // get the log service, if present
- final ServiceReference logRef = context
- .getServiceReference("org.osgi.service.log.LogService"); //$NON-NLS-1$
- if (logRef != null) {
- RemoteOSGiServiceImpl.log = (LogService) context.getService(logRef);
- }
+ if (remoting == null) {
+ // get the instance of RemoteOSGiServiceImpl
+ remoting = new RemoteOSGiServiceImpl();
+ }
- if (remoting == null) {
- // get the instance of RemoteOSGiServiceImpl
- remoting = new RemoteOSGiServiceImpl();
- }
+ // register the default tcp channel
+ if (!"false" //$NON-NLS-1$
+ .equals(context
+ .getProperty(RemoteOSGiServiceImpl.REGISTER_DEFAULT_TCP_CHANNEL))) {
+ final Dictionary properties = new Hashtable();
+ properties.put(NetworkChannelFactory.PROTOCOL_PROPERTY,
+ TCPChannelFactory.PROTOCOL);
+ context.registerService(NetworkChannelFactory.class.getName(),
+ new TCPChannelFactory(), properties);
+ }
- // and register the service
- context.registerService(new String[] {
- RemoteOSGiService.class.getName(), Remoting.class.getName() }, remoting, null);
+ final Hashtable props = new Hashtable();
- // register the default tcp channel
- if (!"false" //$NON-NLS-1$
- .equals(context
- .getProperty(RemoteOSGiServiceImpl.REGISTER_DEFAULT_TCP_CHANNEL))) {
- final Dictionary properties = new Hashtable();
- properties.put(NetworkChannelFactory.PROTOCOL_PROPERTY,
- TCPChannelFactory.PROTOCOL);
- context.registerService(NetworkChannelFactory.class.getName(),
- new TCPChannelFactory(), properties);
- // TODO: add default transport supported intents
+ // and register the service
+ context.registerService(
+ new String[] { RemoteOSGiService.class.getName(),
+ Remoting.class.getName() }, remoting, props);
+ } catch (final Throwable t) {
+ t.printStackTrace();
+ throw new BundleException("Exception while starting R-OSGi", t);
}
}
diff --git a/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/RemoteOSGiServiceImpl.java b/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/RemoteOSGiServiceImpl.java
index df0292fe8..9c747230a 100644
--- a/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/RemoteOSGiServiceImpl.java
+++ b/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/RemoteOSGiServiceImpl.java
@@ -52,6 +52,7 @@ import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import java.util.zip.CRC32;
+import org.objectweb.asm.Type;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
@@ -62,6 +63,7 @@ import org.osgi.service.event.EventAdmin;
import org.osgi.service.event.EventConstants;
import org.osgi.service.event.EventHandler;
import org.osgi.service.log.LogService;
+import org.osgi.service.packageadmin.ExportedPackage;
import org.osgi.service.packageadmin.PackageAdmin;
import org.osgi.util.tracker.ServiceTracker;
import org.osgi.util.tracker.ServiceTrackerCustomizer;
@@ -128,8 +130,15 @@ final class RemoteOSGiServiceImpl implements RemoteOSGiService, Remoting {
getEntry = m;
getEntryPaths = n;
- base = getEntry == null ? RemoteOSGiActivator.getActivator()
- .getContext().getDataFile("../..") : null;
+ File b = null;
+ try {
+ b = getEntry == null ? RemoteOSGiActivator.getActivator()
+ .getContext().getDataFile("../..").getCanonicalFile()
+ : null;
+ } catch (IOException ioe) {
+ ioe.printStackTrace();
+ }
+ base = b;
}
/**
@@ -195,7 +204,7 @@ final class RemoteOSGiServiceImpl implements RemoteOSGiService, Remoting {
* how many worker threads per endpoint?
*/
static final int MAX_THREADS_PER_ENDPOINT = Integer.getInteger(
- THREADS_PER_ENDPOINT, 2).intValue();
+ THREADS_PER_ENDPOINT, 16).intValue();
/**
* log proxy generation debug output.
@@ -233,6 +242,11 @@ final class RemoteOSGiServiceImpl implements RemoteOSGiService, Remoting {
static LogService log;
/**
+ *
+ */
+ static ServiceTracker logServiceTracker;
+
+ /**
* the event admin tracker
*/
static ServiceTracker eventAdminTracker;
@@ -271,7 +285,7 @@ final class RemoteOSGiServiceImpl implements RemoteOSGiService, Remoting {
* Channel ID --> ChannelEndpointMultiplexer
*/
private static Map multiplexers = new HashMap(0);
-
+
/**
* Event topics this instance is going to ignore and not remote
*/
@@ -312,6 +326,28 @@ final class RemoteOSGiServiceImpl implements RemoteOSGiService, Remoting {
// set the debug switches
final BundleContext context = RemoteOSGiActivator.getActivator()
.getContext();
+
+ logServiceTracker = new ServiceTracker(context,
+ LogService.class.getName(), new ServiceTrackerCustomizer() {
+
+ public Object addingService(ServiceReference reference) {
+ System.err.println("LOG SERVICE ATTACHED");
+ log = (LogService) context.getService(reference);
+ return log;
+ }
+
+ public void modifiedService(ServiceReference reference,
+ Object service) {
+
+ }
+
+ public void removedService(ServiceReference reference,
+ Object service) {
+ log = (LogService) logServiceTracker.getService();
+ }
+
+ });
+
String prop = context.getProperty(PROXY_DEBUG_PROPERTY);
PROXY_DEBUG = prop != null ? Boolean.valueOf(prop).booleanValue()
: false;
@@ -333,10 +369,7 @@ final class RemoteOSGiServiceImpl implements RemoteOSGiService, Remoting {
} else {
if (PROXY_DEBUG || MSG_DEBUG || DEBUG) {
System.err
- .println("WARNING: NO LOG SERVICE PRESENT, DEBUG PROPERTIES HAVE NO EFFECT ..."); //$NON-NLS-1$
- PROXY_DEBUG = false;
- MSG_DEBUG = false;
- DEBUG = false;
+ .println("WARNING: NO LOG SERVICE PRESENT, DEBUG PROPERTIES HAVE NO EFFECT UNTIL A LOG SERVICE HAS BEEN STARTED"); //$NON-NLS-1$
}
}
@@ -469,7 +502,7 @@ final class RemoteOSGiServiceImpl implements RemoteOSGiService, Remoting {
});
eventHandlerTracker.open();
- if (DEBUG) {
+ if (DEBUG && log != null) {
log.log(LogService.LOG_DEBUG, "Local topic space " //$NON-NLS-1$
+ Arrays.asList(getTopics()));
}
@@ -573,6 +606,9 @@ final class RemoteOSGiServiceImpl implements RemoteOSGiService, Remoting {
e.printStackTrace();
throw new RemoteOSGiException(
"Cannot find class " + service, e); //$NON-NLS-1$
+ } catch (final RemoteOSGiException r) {
+ r.printStackTrace();
+ throw r;
}
}
@@ -586,6 +622,7 @@ final class RemoteOSGiServiceImpl implements RemoteOSGiService, Remoting {
final RemoteServiceRegistration reg = (RemoteServiceRegistration) serviceRegistrations
.get(reference);
+ unregisterFromServiceDiscovery(reg);
registerWithServiceDiscovery(reg);
final LeaseUpdateMessage lu = new LeaseUpdateMessage();
@@ -638,9 +675,10 @@ final class RemoteOSGiServiceImpl implements RemoteOSGiService, Remoting {
factory.activate(RemoteOSGiServiceImpl.this);
} catch (final IOException ioe) {
if (log != null) {
- log.log(LogService.LOG_ERROR, ioe
- .getMessage(), ioe);
+ log.log(LogService.LOG_ERROR,
+ ioe.getMessage(), ioe);
}
+ ioe.printStackTrace();
}
return factory;
}
@@ -712,7 +750,9 @@ final class RemoteOSGiServiceImpl implements RemoteOSGiService, Remoting {
final ChannelEndpointImpl test = (ChannelEndpointImpl) channels
.get(endpoint.toString());
if (test != null) {
- test.usageCounter++;
+ synchronized (test) {
+ test.usageCounter++;
+ }
return test.getAllRemoteReferences(null);
}
@@ -746,12 +786,19 @@ final class RemoteOSGiServiceImpl implements RemoteOSGiService, Remoting {
final ChannelEndpointImpl channel = (ChannelEndpointImpl) channels
.get(channelURI);
if (channel != null) {
- if (channel.usageCounter == 1) {
- channel.dispose();
- multiplexers.remove(channelURI);
- } else {
- channel.usageCounter--;
+ synchronized (channel) {
+ if (channel.usageCounter == 1) {
+ channel.dispose();
+ multiplexers.remove(channelURI);
+ } else {
+ channel.usageCounter--;
+ }
}
+ } else {
+ // TODO: to log
+ System.err.println("No channel " + endpoint + " to close ("
+ + channelURI + ")");
+ System.err.println("channels " + channels);
}
}
@@ -1077,6 +1124,7 @@ final class RemoteOSGiServiceImpl implements RemoteOSGiService, Remoting {
*/
static void unregisterChannelEndpoint(final String channelURI) {
channels.remove(channelURI);
+ multiplexers.remove(channelURI);
}
/**
@@ -1144,16 +1192,16 @@ final class RemoteOSGiServiceImpl implements RemoteOSGiService, Remoting {
void registerWithServiceDiscovery(final RemoteServiceRegistration reg) {
// register the service with all service
// discovery handler
+ final Dictionary props = reg.getProperties();
final Object[] handler = serviceDiscoveryHandlerTracker.getServices();
if (handler != null) {
for (int i = 0; i < handler.length; i++) {
- final Dictionary props = reg.getProperties();
- ((ServiceDiscoveryHandler) handler[i]).registerService(reg
- .getReference(), props, URI.create("r-osgi://" //$NON-NLS-1$
- + RemoteOSGiServiceImpl.MY_ADDRESS + ":" //$NON-NLS-1$
- + RemoteOSGiServiceImpl.R_OSGI_PORT + "#" //$NON-NLS-1$
- + reg.getServiceID()));
+ ((ServiceDiscoveryHandler) handler[i]).registerService(
+ reg.getReference(), props, URI.create("r-osgi://" //$NON-NLS-1$
+ + RemoteOSGiServiceImpl.MY_ADDRESS + ":" //$NON-NLS-1$
+ + RemoteOSGiServiceImpl.R_OSGI_PORT + "#" //$NON-NLS-1$
+ + reg.getServiceID()));
}
}
@@ -1200,6 +1248,50 @@ final class RemoteOSGiServiceImpl implements RemoteOSGiService, Remoting {
}
}
+ static String[] getMissingPackages(final String[] packages) {
+ final List missing = new ArrayList();
+ for (int i = 0; i < packages.length; i++) {
+ if (getBundleForPackage(packages[i]) == null) {
+ missing.add(packages[i]);
+ }
+ }
+ return (String[]) missing.toArray(new String[missing.size()]);
+
+ }
+
+ private static Bundle getBundleForPackage(final String packageStr) {
+ ExportedPackage pkg = null;
+ final String pkgString;
+ String versionString = null;
+ final String[] tokens = StringUtils.splitString(packageStr, ";");
+ pkgString = tokens[0];
+ for (int j = 0; j < tokens.length; j++) {
+ if (tokens[j].startsWith("version")) {
+ versionString = tokens[j].substring("version=".length());
+ break;
+ }
+ }
+ if (RemoteOSGiServiceImpl.IS_R4 && versionString != null) {
+ final ExportedPackage[] pkgs = pkgAdmin
+ .getExportedPackages(pkgString);
+ if (pkgs == null) {
+ return null;
+ }
+ for (int j = 0; j < pkgs.length; j++) {
+ final boolean matches = StringUtils.isVersionInRange(
+ pkgs[j].getVersion(), versionString);
+ if (matches
+ && (pkg == null || pkgs[j].getVersion().compareTo(
+ pkg.getVersion()) > 0)) {
+ pkg = pkgs[j];
+ }
+ }
+ } else {
+ pkg = pkgAdmin.getExportedPackage(pkgString);
+ }
+ return pkg == null ? null : pkg.getExportingBundle();
+ }
+
static byte[][] getBundlesForPackages(final String[] packages)
throws IOException {
final HashSet visitedBundles = new HashSet(packages.length);
@@ -1214,10 +1306,9 @@ final class RemoteOSGiServiceImpl implements RemoteOSGiService, Remoting {
BUFFER_SIZE)
: null;
- // TODO: for R4, handle multiple versions
for (int i = 0; i < packages.length; i++) {
- final Bundle bundle = pkgAdmin.getExportedPackage(packages[i])
- .getExportingBundle();
+ final Bundle bundle = getBundleForPackage(packages[i]);
+
if (visitedBundles.contains(bundle)) {
continue;
}
@@ -1260,14 +1351,6 @@ final class RemoteOSGiServiceImpl implements RemoteOSGiService, Remoting {
return out.toByteArray();
}
- static boolean checkPackageImport(final String pkg) {
- // TODO: use versions if on R4
- if (pkg.startsWith("org.osgi")) {
- return true;
- }
- return pkgAdmin.getExportedPackage(pkg) != null;
- }
-
private static byte[] generateBundle(final Bundle bundle,
final String prefix, final byte[] buffer, final CRC32 crc)
throws Exception {
@@ -1305,7 +1388,7 @@ final class RemoteOSGiServiceImpl implements RemoteOSGiService, Remoting {
} else if (entry.endsWith(SEPARATOR_CHAR)) {
scan(bundle, prefix, entry, out, buffer, crc);
} else {
- final URL url = bundle.getResource(prefix + "/" + entry);
+ final URL url = bundle.getEntry(prefix + "/" + entry);
final InputStream in = url.openStream();
int read;
int totallyRead = 0;
@@ -1357,4 +1440,10 @@ final class RemoteOSGiServiceImpl implements RemoteOSGiService, Remoting {
callback);
}
+ public void asyncRemoteCall(final URI service, final Method method,
+ final Object[] args, final AsyncRemoteCallCallback callback) {
+ asyncRemoteCall(service, Type.getMethodDescriptor(method), args,
+ callback);
+ }
+
}
diff --git a/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/RemoteServiceReferenceImpl.java b/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/RemoteServiceReferenceImpl.java
index e0e0184e4..a97695faf 100644
--- a/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/RemoteServiceReferenceImpl.java
+++ b/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/RemoteServiceReferenceImpl.java
@@ -33,6 +33,9 @@ import java.util.Arrays;
import java.util.Dictionary;
import java.util.Enumeration;
+import org.osgi.framework.Constants;
+
+import ch.ethz.iks.r_osgi.RemoteOSGiService;
import ch.ethz.iks.r_osgi.RemoteServiceReference;
import ch.ethz.iks.r_osgi.URI;
@@ -85,9 +88,16 @@ final class RemoteServiceReferenceImpl implements RemoteServiceReference {
final String serviceID, final Dictionary properties,
final ChannelEndpointImpl channel) {
this.serviceInterfaces = serviceInterfaces;
- this.properties = properties;
- this.uri = channel.getRemoteAddress().resolve("#" + serviceID); //$NON-NLS-1$
+ uri = channel.getRemoteAddress().resolve("#" + serviceID); //$NON-NLS-1$
this.properties = properties;
+ // adjust the properties
+ this.properties.put(RemoteOSGiService.SERVICE_URI, uri.toString());
+ // remove the service PID, if set
+ this.properties.remove(Constants.SERVICE_PID);
+ // remove the R-OSGi registration property
+ this.properties.remove(RemoteOSGiService.R_OSGi_REGISTRATION);
+ // also remote the ECF registration property
+ this.properties.remove("org.eclipse.ecf.serviceRegistrationRemote"); //$NON-NLS-1$
this.channel = channel;
}
diff --git a/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/RemoteServiceRegistration.java b/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/RemoteServiceRegistration.java
index 4deafe168..0f3c5cb35 100644
--- a/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/RemoteServiceRegistration.java
+++ b/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/RemoteServiceRegistration.java
@@ -28,6 +28,7 @@
*/
package ch.ethz.iks.r_osgi.impl;
+import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Dictionary;
import java.util.HashMap;
@@ -38,6 +39,7 @@ import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
import org.osgi.service.log.LogService;
+import ch.ethz.iks.r_osgi.RemoteOSGiException;
import ch.ethz.iks.r_osgi.RemoteOSGiService;
import ch.ethz.iks.r_osgi.messages.DeliverServiceMessage;
@@ -76,7 +78,7 @@ final class RemoteServiceRegistration {
/**
* a prefactored deliver service message.
*/
- private DeliverServiceMessage deliverServiceMessage;
+ private volatile DeliverServiceMessage deliverServiceMessage;
/**
* creates a new RemoteService object.
@@ -115,6 +117,11 @@ final class RemoteServiceRegistration {
// build up the method table for each interface
for (int i = 0; i < interfaceCount; i++) {
serviceInterfaces[i] = bundleLoader.loadClass(interfaceNames[i]);
+ if (!serviceInterfaces[i].isInterface()) {
+ throw new RemoteOSGiException(
+ "Service registered under non-interface "
+ + serviceInterfaces[i].getName());
+ }
final Method[] methods = serviceInterfaces[i].getMethods();
for (int j = 0; j < methods.length; j++) {
methodTable.put(methods[j].getName()
@@ -126,19 +133,40 @@ final class RemoteServiceRegistration {
final CodeAnalyzer analyzer = new CodeAnalyzer(bundleLoader,
(String) headers.get(Constants.IMPORT_PACKAGE),
(String) headers.get(Constants.EXPORT_PACKAGE));
- try {
- deliverServiceMessage = analyzer.analyze(interfaceNames,
- (String) ref.getProperty(RemoteOSGiService.SMART_PROXY),
- (String[]) ref.getProperty(RemoteOSGiService.INJECTIONS),
- (String) ref.getProperty(RemoteOSGiService.PRESENTATION));
- deliverServiceMessage.setServiceID(((Long) ref
- .getProperty(Constants.SERVICE_ID)).toString());
- } catch (final Exception e) {
- if (RemoteOSGiServiceImpl.log != null) {
- RemoteOSGiServiceImpl.log.log(LogService.LOG_ERROR,
- "Error during remote service registration", e); //$NON-NLS-1$
+ new Thread() {
+ public void run() {
+ synchronized (RemoteServiceRegistration.this) {
+ try {
+ deliverServiceMessage = analyzer
+ .analyze(
+ interfaceNames,
+ (String) ref
+ .getProperty(RemoteOSGiService.SMART_PROXY),
+ (String[]) ref
+ .getProperty(RemoteOSGiService.INJECTIONS),
+ (String) ref
+ .getProperty(RemoteOSGiService.PRESENTATION));
+ deliverServiceMessage.setServiceID(((Long) ref
+ .getProperty(Constants.SERVICE_ID)).toString());
+ } catch (final IOException e) {
+ e.printStackTrace();
+ if (RemoteOSGiServiceImpl.log != null) {
+ RemoteOSGiServiceImpl.log
+ .log(LogService.LOG_ERROR,
+ "Error during remote service registration", e); //$NON-NLS-1$
+ }
+ } catch (final ClassNotFoundException cnf) {
+ cnf.printStackTrace();
+ if (RemoteOSGiServiceImpl.log != null) {
+ RemoteOSGiServiceImpl.log
+ .log(LogService.LOG_ERROR,
+ "Error during remote service registration", cnf); //$NON-NLS-1$
+ }
+ }
+ RemoteServiceRegistration.this.notifyAll();
+ }
}
- }
+ }.start();
}
/**
@@ -239,7 +267,16 @@ final class RemoteServiceRegistration {
* @return the message.
*/
DeliverServiceMessage getDeliverServiceMessage() {
- return deliverServiceMessage;
+ synchronized (this) {
+ if (deliverServiceMessage == null) {
+ try {
+ wait();
+ } catch (final InterruptedException e) {
+ // ignore
+ }
+ }
+ return deliverServiceMessage;
+ }
}
public String toString() {
diff --git a/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/TCPChannelFactory.java b/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/TCPChannelFactory.java
index a7eb1f72e..f5058c50e 100644
--- a/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/TCPChannelFactory.java
+++ b/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/impl/TCPChannelFactory.java
@@ -36,6 +36,7 @@ import java.io.IOException;
import java.net.BindException;
import java.net.ServerSocket;
import java.net.Socket;
+import java.net.SocketException;
import org.osgi.service.log.LogService;
@@ -56,6 +57,8 @@ import ch.ethz.iks.util.SmartObjectOutputStream;
*/
final class TCPChannelFactory implements NetworkChannelFactory {
+ public static final boolean beSmart = true;
+
static final String PROTOCOL = "r-osgi"; //$NON-NLS-1$
Remoting remoting;
private TCPAcceptorThread thread;
@@ -93,8 +96,9 @@ final class TCPChannelFactory implements NetworkChannelFactory {
* @see ch.ethz.iks.r_osgi.channels.NetworkChannelFactory#deactivate(ch.ethz.iks.r_osgi.Remoting)
*/
public void deactivate(final Remoting r) throws IOException {
- if(thread != null) {
- thread.interrupt();
+ if (thread != null) {
+ thread.close();
+ thread = null;
}
remoting = null;
}
@@ -219,11 +223,17 @@ final class TCPChannelFactory implements NetworkChannelFactory {
// for 1.2 VMs that do not support the setKeepAlive
}
socket.setTcpNoDelay(true);
- output = new SmartObjectOutputStream(new BufferedOutputStream(
- socket.getOutputStream()));
- output.flush();
- input = new SmartObjectInputStream(new BufferedInputStream(socket
- .getInputStream()));
+ if (beSmart) {
+ output = new SmartObjectOutputStream(socket.getOutputStream());
+ output.flush();
+ input = new SmartObjectInputStream(socket.getInputStream());
+ } else {
+ output = new ObjectOutputStream(new BufferedOutputStream(
+ socket.getOutputStream()));
+ output.flush();
+ input = new ObjectInputStream(new BufferedInputStream(
+ socket.getInputStream()));
+ }
}
/**
@@ -284,7 +294,7 @@ final class TCPChannelFactory implements NetworkChannelFactory {
*/
public void sendMessage(final RemoteOSGiMessage message)
throws IOException {
- if (RemoteOSGiServiceImpl.MSG_DEBUG) {
+ if (RemoteOSGiServiceImpl.MSG_DEBUG && RemoteOSGiServiceImpl.log != null) {
RemoteOSGiServiceImpl.log.log(LogService.LOG_DEBUG,
"{TCP Channel} sending " + message); //$NON-NLS-1$
}
@@ -309,7 +319,7 @@ final class TCPChannelFactory implements NetworkChannelFactory {
try {
final RemoteOSGiMessage msg = RemoteOSGiMessage
.parse(input);
- if (RemoteOSGiServiceImpl.MSG_DEBUG) {
+ if (RemoteOSGiServiceImpl.MSG_DEBUG && RemoteOSGiServiceImpl.log != null) {
RemoteOSGiServiceImpl.log.log(LogService.LOG_DEBUG,
"{TCP Channel} received " + msg); //$NON-NLS-1$
}
@@ -365,6 +375,11 @@ final class TCPChannelFactory implements NetworkChannelFactory {
RemoteOSGiServiceImpl.R_OSGI_PORT = listeningPort;
return;
} catch (final BindException b) {
+ // normal behavior, get a BindException if the port is
+ // already in use
+ e++;
+ } catch (final SocketException s) {
+ // Windows 7 behavior
e++;
}
}
@@ -382,10 +397,15 @@ final class TCPChannelFactory implements NetworkChannelFactory {
// for them
remoting.createEndpoint(new TCPChannel(socket.accept()));
} catch (final IOException ioe) {
- ioe.printStackTrace();
+ // TODO: to log
}
}
}
+
+ public void close() throws IOException {
+ interrupt();
+ socket.close();
+ }
}
}
diff --git a/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/messages/DeliverServiceMessage.java b/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/messages/DeliverServiceMessage.java
index 8e541cf90..5ca32f72a 100644
--- a/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/messages/DeliverServiceMessage.java
+++ b/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/messages/DeliverServiceMessage.java
@@ -173,7 +173,6 @@ public final class DeliverServiceMessage extends RemoteOSGiMessage {
+ pkgName + ";resolution:=optional";
}
}
-
}
/**
diff --git a/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/messages/RemoteOSGiMessage.java b/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/messages/RemoteOSGiMessage.java
index bc36e040e..5187b24fa 100644
--- a/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/messages/RemoteOSGiMessage.java
+++ b/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/r_osgi/messages/RemoteOSGiMessage.java
@@ -258,7 +258,7 @@ public abstract class RemoteOSGiMessage {
out.write(funcID);
out.writeInt(xid);
writeBody(out);
- out.reset();
+ //out.reset();
out.flush();
}
}
diff --git a/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/util/SmartObjectInputStream.java b/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/util/SmartObjectInputStream.java
index 8a28c1b4d..469461fbb 100644
--- a/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/util/SmartObjectInputStream.java
+++ b/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/util/SmartObjectInputStream.java
@@ -32,9 +32,9 @@ package ch.ethz.iks.util;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
-import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
+import java.lang.reflect.Method;
+import java.util.zip.GZIPInputStream;
/**
* Smart object input stream that is able to deserialize classes which do not
@@ -46,251 +46,50 @@ import java.lang.reflect.Modifier;
*/
public final class SmartObjectInputStream extends ObjectInputStream {
- private final ObjectInputStream in;
+ private Object handles;
+ private Field handle;
+ private Method setHandle;
public SmartObjectInputStream(final InputStream in) throws IOException {
- // implicitly: super();
- // thereby, enableOverride is set
- this.in = new ObjectInputStream(in);
+ super(new GZIPInputStream(in));
+ enableResolveObject(true);
+ try {
+ final Field field = getClass().getSuperclass().getDeclaredField(
+ "handles");
+ field.setAccessible(true);
+ handles = field.get(this);
+ handle = getClass().getSuperclass().getDeclaredField("passHandle");
+ handle.setAccessible(true);
+ setHandle = handles.getClass().getDeclaredMethod("setObject",
+ new Class[] { Integer.TYPE, Object.class });
+ setHandle.setAccessible(true);
+ } catch (Exception e) {
+ // handle replacement won't work.
+ }
}
- protected final Object readObjectOverride() throws IOException,
- ClassNotFoundException {
-
- final byte cat = in.readByte();
- switch (cat) {
- case 0:
- // null
- return null;
- case 1:
- // string serialized object
- // TODO: cache constructors
+ protected Object resolveObject(final Object obj) throws IOException {
+ if (obj instanceof SmartObjectStreamClass) {
try {
- final String type = in.readUTF();
- final Class test = (Class) SmartConstants.idToClass.get(type);
- final Class clazz = test != null ? test : Class.forName(type);
- final Constructor constr = clazz
- .getConstructor(new Class[] { String.class });
- return constr.newInstance(new Object[] { in.readUTF() });
- } catch (final Exception e) {
- e.printStackTrace();
- throw new IOException(e.getMessage());
- }
- case 2:
- // java serialized object
- return in.readObject();
- case 3:
- return readSmartSerializedObject();
- case 4:
- final int length = in.readByte();
- final String clazzName = in.readUTF();
- final Class clazz = Class.forName(clazzName);
- final Object[] array = (Object[]) java.lang.reflect.Array
- .newInstance(clazz, length);
- for (int i = 0; i < length; i++) {
- final byte b = in.readByte();
- if(b == -1) {
- array[i] = null;
- } else {
- array[i] = readSmartSerializedObject();
- }
+ return ((SmartObjectStreamClass) obj).restoreObject();
+ } catch (Exception e) {
+ final IOException f = new IOException(
+ "Exception while resolving object");
+ f.initCause(e);
+ throw f;
}
- return array;
- default:
- throw new IllegalStateException("Unhandled case " + cat); //$NON-NLS-1$
}
+ return obj;
}
- private Object readSmartSerializedObject() throws IOException, ClassNotFoundException {
- // smart serialized object
- final String clazzName = in.readUTF();
-
- // TODO: cache this information...
- Class clazz = Class.forName(clazzName);
-
+ void fixHandle(final Object obj) {
+ if (setHandle == null) {
+ return;
+ }
try {
- final Constructor constr = clazz.getDeclaredConstructor(null);
- constr.setAccessible(true);
- final Object newInstance = constr.newInstance(null);
-
- int fieldCount = in.readInt();
- while (fieldCount > -1) {
- for (int i = 0; i < fieldCount; i++) {
- final String fieldName = in.readUTF();
- final Object value = readObjectOverride();
- final Field field = clazz.getDeclaredField(fieldName);
-
- final int mod = field.getModifiers();
- if (!Modifier.isPublic(mod)) {
- field.setAccessible(true);
- }
-
- field.set(newInstance, value);
- }
- clazz = clazz.getSuperclass();
- fieldCount = in.readInt();
- }
- return newInstance;
- } catch (final Exception e) {
+ setHandle.invoke(handles, new Object[] { handle.get(this), obj });
+ } catch (Exception e) {
e.printStackTrace();
- throw new IOException("Error while deserializing " + clazzName //$NON-NLS-1$
- + ": " + e.getMessage()); //$NON-NLS-1$
}
}
-
- /**
- *
- * @see java.io.ObjectInputStream#read()
- */
- public final int read() throws IOException {
- return in.read();
- }
-
- /**
- *
- * @see java.io.ObjectInputStream#read(byte[], int, int)
- */
- public final int read(final byte[] buf, final int off, final int len)
- throws IOException {
- return in.read(buf, off, len);
- }
-
- /**
- *
- * @see java.io.ObjectInputStream#available()
- */
- public final int available() throws IOException {
- return in.available();
- }
-
- /**
- *
- * @see java.io.ObjectInputStream#close()
- */
- public final void close() throws IOException {
- in.close();
- }
-
- /**
- *
- * @see java.io.ObjectInputStream#readBoolean()
- */
- public final boolean readBoolean() throws IOException {
- return in.readBoolean();
- }
-
- /**
- *
- * @see java.io.ObjectInputStream#readByte()
- */
- public final byte readByte() throws IOException {
- return in.readByte();
- }
-
- /**
- *
- * @see java.io.ObjectInputStream#readUnsignedByte()
- */
- public final int readUnsignedByte() throws IOException {
- return in.readUnsignedByte();
- }
-
- /**
- *
- * @see java.io.ObjectInputStream#readChar()
- */
- public final char readChar() throws IOException {
- return in.readChar();
- }
-
- /**
- *
- * @see java.io.ObjectInputStream#readShort()
- */
- public final short readShort() throws IOException {
- return in.readShort();
- }
-
- /**
- *
- * @see java.io.ObjectInputStream#readUnsignedShort()
- */
- public final int readUnsignedShort() throws IOException {
- return in.readUnsignedShort();
- }
-
- /**
- *
- * @see java.io.ObjectInputStream#readInt()
- */
- public final int readInt() throws IOException {
- return in.readInt();
- }
-
- /**
- *
- * @see java.io.ObjectInputStream#readLong()
- */
- public final long readLong() throws IOException {
- return in.readLong();
- }
-
- /**
- *
- * @see java.io.ObjectInputStream#readFloat()
- */
- public final float readFloat() throws IOException {
- return in.readFloat();
- }
-
- /**
- *
- * @see java.io.ObjectInputStream#readDouble()
- */
- public final double readDouble() throws IOException {
- return in.readDouble();
- }
-
- /**
- *
- * @see java.io.ObjectInputStream#readFully(byte[])
- */
- public final void readFully(final byte[] buf) throws IOException {
- in.readFully(buf);
- }
-
- /**
- *
- * @see java.io.ObjectInputStream#readFully(byte[], int, int)
- */
- public final void readFully(final byte[] buf, final int off, final int len)
- throws IOException {
- in.readFully(buf, off, len);
- }
-
- /**
- *
- * @see java.io.ObjectInputStream#skipBytes(int)
- */
- public final int skipBytes(final int len) throws IOException {
- return in.skipBytes(len);
- }
-
- /**
- * @return String
- * @throws IOException
- * @deprecated
- */
- public final String readLine() throws IOException {
- return in.readLine();
- }
-
- /**
- *
- * @see java.io.ObjectInputStream#readUTF()
- */
- public final String readUTF() throws IOException {
- return in.readUTF();
- }
-
}
diff --git a/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/util/SmartObjectOutputStream.java b/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/util/SmartObjectOutputStream.java
index d352af1d0..0899636a6 100644
--- a/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/util/SmartObjectOutputStream.java
+++ b/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/util/SmartObjectOutputStream.java
@@ -1,6 +1,5 @@
-/* Copyright (c) 2006-2009 Jan S. Rellermeyer
- * Systems Group,
- * Institute for Pervasive Computing, ETH Zurich.
+/* Copyright (c) 2006-2011 Jan S. Rellermeyer
+ * Systems Group, ETH Zurich.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,9 +33,10 @@ import java.io.NotSerializableException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.zip.Deflater;
+import java.util.zip.GZIPOutputStream;
import ch.ethz.iks.r_osgi.types.BoxedPrimitive;
@@ -46,269 +46,80 @@ import ch.ethz.iks.r_osgi.types.BoxedPrimitive;
* and the OSGi ServiceReference and ServiceRegistration classes.
*
* @author Jan S. Rellermeyer
- *
*/
public final class SmartObjectOutputStream extends ObjectOutputStream {
- private final ObjectOutputStream out;
+ static Set blackList = new HashSet();
+ static {
+ blackList.add("org.osgi.framework.ServiceReference"); //$NON-NLS-1$
+ blackList.add("org.osgi.framework.ServiceRegistration"); //$NON-NLS-1$
+ }
public SmartObjectOutputStream(final OutputStream out) throws IOException {
- // implicitly: super();
- // thereby, enableOverride is set
- this.out = new ObjectOutputStream(out);
+ super(new EnhancedGZIPOutputStream(out));
+ this.enableReplaceObject(true);
}
- protected final void writeObjectOverride(final Object o) throws IOException {
- if (o == null) {
- out.writeByte(0);
- return;
+ protected Object replaceObject(final Object obj) throws IOException {
+ if (obj instanceof BoxedPrimitive) {
+ return ((BoxedPrimitive) obj).getBoxed();
}
- final Object obj = o instanceof BoxedPrimitive ? ((BoxedPrimitive) o)
- .getBoxed() : o;
-
- final String clazzName = obj.getClass().getName();
- if (SmartConstants.positiveList.contains(clazzName)) {
- // string serializable classes
- out.writeByte(1);
- final String id = (String) SmartConstants.classToId.get(clazzName);
- out.writeUTF(id != null ? id : clazzName);
- out.writeUTF(obj.toString());
- return;
- } else if (isNestedSmartSerializedObject(obj)) {
- final Object[] objArray = (Object[]) obj;
- final String clazzname = objArray.getClass().getName();
- out.write(4);
- out.writeByte(objArray.length);
- out.writeUTF(clazzname.substring(2, clazzname.length() - 1));
- for (int i = 0; i < objArray.length; i++) {
- final Object elem = objArray[i];
- if(elem == null) {
- out.writeByte(-1);
- } else {
- writeSmartSerializedObject(elem);
- }
- }
- } else if (obj instanceof Serializable) {
- // java serializable classes
- out.writeByte(2);
- out.writeObject(obj);
- return;
- } else {
- writeSmartSerializedObject(obj);
+ if (obj instanceof Serializable) {
+ return obj;
}
- }
- private boolean isNestedSmartSerializedObject(final Object obj) {
- if(obj != null && obj instanceof Object[]) {
- Object[] objArray = (Object[]) obj;
- if(objArray.length > 0) {
- // iterate to skip null
- for(int i = 0; i < objArray.length; i++) {
- if(objArray[i] instanceof Serializable) {
- return false;
- }
- }
- return true;
- }
+ final Class clazz = obj.getClass();
+ if (blackList.contains(clazz.getName())) {
+ throw new NotSerializableException(clazz.getName());
}
- return false;
+
+ return new SmartObjectStreamClass(obj, clazz);
}
- private void writeSmartSerializedObject(final Object obj) throws IOException,
- NotSerializableException {
- out.writeByte(3);
+ static class EnhancedGZIPOutputStream extends GZIPOutputStream {
- // all other classes: try smart serialization
- Class clazz = obj.getClass();
+ private static final byte[] NOTHING = new byte[0];
+ private boolean hasPendingBytes = false;
- if (SmartConstants.blackList.contains(clazz.getName())) {
- throw new NotSerializableException("Class " + clazz.getName() //$NON-NLS-1$
- + " is not serializable"); //$NON-NLS-1$
+ public EnhancedGZIPOutputStream(final OutputStream out)
+ throws IOException {
+ super(out);
+ def.setLevel(Deflater.BEST_SPEED);
}
- out.writeUTF(clazz.getName());
-
- // TODO: cache this information...
- while (clazz != Object.class) {
- // check for native methods
- final Method[] methods = clazz.getDeclaredMethods();
- for (int j = 0; j < methods.length; j++) {
- final int mod = methods[j].getModifiers();
- if (Modifier.isNative(mod)) {
- throw new NotSerializableException(
- "Class " //$NON-NLS-1$
- + clazz.getName()
- + " contains native methods and is therefore not serializable."); //$NON-NLS-1$
- }
- }
+ public void write(final byte[] bytes, final int i, final int i1)
+ throws IOException {
+ super.write(bytes, i, i1);
+ hasPendingBytes = true;
+ }
- try {
- final Field[] fields = clazz.getDeclaredFields();
- final int fieldCount = fields.length;
- int realFieldCount = 0;
- for (int i = 0; i < fieldCount; i++) {
- final int mod = fields[i].getModifiers();
- if (!(Modifier.isStatic(mod) || Modifier.isTransient(mod))) {
- realFieldCount++;
- }
- }
- out.writeInt(realFieldCount);
- for (int i = 0; i < fieldCount; i++) {
- final int mod = fields[i].getModifiers();
- if (Modifier.isStatic(mod) || Modifier.isTransient(mod)) {
- continue;
- } else if (!Modifier.isPublic(mod)) {
- fields[i].setAccessible(true);
- }
- out.writeUTF(fields[i].getName());
- writeObjectOverride(fields[i].get(obj));
+ protected void deflate() throws IOException {
+ int len;
+ do {
+ len = def.deflate(buf, 0, buf.length);
+ if (len == 0) {
+ break;
}
- } catch (final Exception e) {
- throw new NotSerializableException(
- "Exception while serializing " + obj.toString() //$NON-NLS-1$
- + ":\n" + e.getMessage()); //$NON-NLS-1$
- }
- clazz = clazz.getSuperclass();
+ this.out.write(buf, 0, len);
+ } while (true);
}
- out.writeInt(-1);
- }
-
- /**
- *
- * @see java.io.ObjectOutputStream#write(int)
- */
- public final void write(final int val) throws IOException {
- out.write(val);
- }
-
- /**
- *
- * @see java.io.ObjectOutputStream#write(byte[])
- */
- public final void write(final byte[] buf) throws IOException {
- out.write(buf);
- }
-
- /**
- *
- * @see java.io.ObjectOutputStream#write(byte[], int, int)
- */
- public final void write(final byte[] buf, final int off, final int len)
- throws IOException {
- out.write(buf, off, len);
- }
-
- /**
- *
- * @see java.io.ObjectOutputStream#flush()
- */
- public final void flush() throws IOException {
- out.flush();
- }
-
- /**
- *
- * @see java.io.ObjectOutputStream#reset()
- */
- public final void reset() throws IOException {
- out.reset();
- }
- /**
- *
- * @see java.io.ObjectOutputStream#close()
- */
- public final void close() throws IOException {
- out.close();
- }
-
- /**
- *
- * @see java.io.ObjectOutputStream#writeBoolean(boolean)
- */
- public final void writeBoolean(final boolean val) throws IOException {
- out.writeBoolean(val);
- }
-
- /**
- *
- * @see java.io.ObjectOutputStream#writeByte(int)
- */
- public final void writeByte(final int val) throws IOException {
- out.writeByte(val);
- }
-
- /**
- *
- * @see java.io.ObjectOutputStream#writeShort(int)
- */
- public final void writeShort(final int val) throws IOException {
- out.writeShort(val);
- }
-
- /**
- *
- * @see java.io.ObjectOutputStream#writeChar(int)
- */
- public final void writeChar(final int val) throws IOException {
- out.writeChar(val);
- }
-
- /**
- *
- * @see java.io.ObjectOutputStream#writeInt(int)
- */
- public final void writeInt(final int val) throws IOException {
- out.writeInt(val);
- }
-
- /**
- *
- * @see java.io.ObjectOutputStream#writeLong(long)
- */
- public final void writeLong(final long val) throws IOException {
- out.writeLong(val);
- }
-
- /**
- *
- * @see java.io.ObjectOutputStream#writeFloat(float)
- */
- public final void writeFloat(final float val) throws IOException {
- out.writeFloat(val);
- }
-
- /**
- *
- * @see java.io.ObjectOutputStream#writeDouble(double)
- */
- public final void writeDouble(final double val) throws IOException {
- out.writeDouble(val);
- }
-
- /**
- *
- * @see java.io.ObjectOutputStream#writeBytes(java.lang.String)
- */
- public final void writeBytes(final String str) throws IOException {
- out.writeBytes(str);
- }
+ public void flush() throws IOException {
+ if (!hasPendingBytes) {
+ return;
+ }
- /**
- *
- * @see java.io.ObjectOutputStream#writeChars(java.lang.String)
- */
- public final void writeChars(final String str) throws IOException {
- out.writeChars(str);
- }
+ if (!def.finished()) {
+ def.setInput(NOTHING, 0, 0);
+ def.setLevel(Deflater.NO_COMPRESSION);
+ deflate();
+ def.setLevel(Deflater.BEST_SPEED);
+ deflate();
+ super.flush();
+ }
- /**
- *
- * @see java.io.ObjectOutputStream#writeUTF(java.lang.String)
- */
- public final void writeUTF(final String str) throws IOException {
- out.writeUTF(str);
+ hasPendingBytes = false;
+ }
}
-
}
diff --git a/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/util/SmartObjectStreamClass.java b/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/util/SmartObjectStreamClass.java
new file mode 100644
index 000000000..ba8e74b1b
--- /dev/null
+++ b/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/util/SmartObjectStreamClass.java
@@ -0,0 +1,150 @@
+package ch.ethz.iks.util;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.NotSerializableException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.WeakHashMap;
+
+public class SmartObjectStreamClass implements Externalizable {
+
+ private String clazzName;
+ private String[] fieldNames;
+ private Object[] fieldValues;
+ private SmartObjectStreamClass superStreamClass;
+ private transient Object restored;
+
+ static final WeakHashMap fieldInfoCache = new WeakHashMap();
+
+ public SmartObjectStreamClass(final Object obj, final Class clazz)
+ throws NotSerializableException {
+
+ clazzName = clazz.getName();
+
+ final String[] fieldInfo = (String[]) fieldInfoCache.get(clazzName);
+
+ final Field[] fields = clazz.getDeclaredFields();
+ final int fieldCount = fields.length;
+
+ try {
+ if (fieldInfo == null) {
+ // check for native methods
+ final Method[] methods = clazz.getDeclaredMethods();
+ for (int i = 0; i < methods.length; i++) {
+ final int mod = methods[i].getModifiers();
+ if (Modifier.isNative(mod)) {
+ SmartObjectOutputStream.blackList.add(clazz);
+ throw new NotSerializableException(
+ "Class " //$NON-NLS-1$
+ + clazz.getName()
+ + " contains native methods and is therefore not serializable."); //$NON-NLS-1$
+ }
+ }
+
+ int realFieldCount = 0;
+ for (int i = 0; i < fieldCount; i++) {
+ final int mod = fields[i].getModifiers();
+ if (!(Modifier.isStatic(mod) || Modifier.isTransient(mod))) {
+ realFieldCount++;
+ }
+ }
+ fieldNames = new String[realFieldCount];
+ fieldInfoCache.put(clazzName, fieldNames);
+ } else {
+ fieldNames = fieldInfo;
+ }
+
+ fieldValues = new Object[fieldNames.length];
+
+ for (int i = 0; i < fieldCount; i++) {
+ final int mod = fields[i].getModifiers();
+ if (Modifier.isStatic(mod) || Modifier.isTransient(mod)) {
+ continue;
+ } else if (!Modifier.isPublic(mod)) {
+ fields[i].setAccessible(true);
+ }
+ fieldNames[i] = fields[i].getName();
+ fieldValues[i] = fields[i].get(obj);
+ }
+ } catch (final Exception e) {
+ SmartObjectOutputStream.blackList.add(clazz);
+ throw new NotSerializableException(
+ "Exception while serializing " + obj.toString() //$NON-NLS-1$
+ + ":\n" + e.getMessage()); //$NON-NLS-1$
+ }
+
+ final Class superClazz = clazz.getSuperclass();
+ if (superClazz != null && superClazz != Object.class) {
+ superStreamClass = new SmartObjectStreamClass(obj, superClazz);
+ }
+ }
+
+ public SmartObjectStreamClass() {
+
+ }
+
+ public void writeExternal(final ObjectOutput out) throws IOException {
+ out.writeUTF(clazzName);
+ out.writeInt(fieldNames.length);
+ for (int i = 0; i < fieldNames.length; i++) {
+ out.writeUTF(fieldNames[i]);
+ out.writeObject(fieldValues[i]);
+ }
+ }
+
+ public void readExternal(final ObjectInput in) throws IOException,
+ ClassNotFoundException {
+ clazzName = in.readUTF();
+
+ try {
+ final Class clazz = Class.forName(clazzName);
+ final Constructor constr = clazz.getDeclaredConstructor(null);
+ constr.setAccessible(true);
+ restored = constr.newInstance(null);
+ } catch (Exception e) {
+ final IOException f = new IOException(
+ "Exception while resolving object");
+ f.initCause(e);
+ throw f;
+ }
+
+ ((SmartObjectInputStream) in).fixHandle(restored);
+
+ final int fieldCount = in.readInt();
+ fieldNames = new String[fieldCount];
+ fieldValues = new Object[fieldCount];
+ for (int i = 0; i < fieldCount; i++) {
+ fieldNames[i] = in.readUTF();
+ fieldValues[i] = in.readObject();
+ }
+ }
+
+ public Object restoreObject() throws Exception {
+ restoreFields(restored);
+ return restored;
+ }
+
+ private void restoreFields(final Object o) throws Exception {
+ final Class clazz = Class.forName(clazzName);
+ for (int i = 0; i < fieldNames.length; i++) {
+ final Field field = clazz.getDeclaredField(fieldNames[i]);
+
+ final int mod = field.getModifiers();
+ if (!Modifier.isPublic(mod)) {
+ field.setAccessible(true);
+ }
+
+ field.set(o, fieldValues[i]);
+ }
+
+ if (superStreamClass != null) {
+ superStreamClass.restoreFields(o);
+ }
+ }
+
+}
diff --git a/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/util/StringUtils.java b/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/util/StringUtils.java
index 79f6bcec2..66b2a5c3a 100644
--- a/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/util/StringUtils.java
+++ b/protocols/bundles/ch.ethz.iks.r_osgi.remote/src/main/java/ch/ethz/iks/util/StringUtils.java
@@ -34,6 +34,8 @@ import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;
+import org.osgi.framework.Version;
+
/**
* String utilities.
*
@@ -48,6 +50,140 @@ public final class StringUtils {
private StringUtils() {
}
+ public static String[] splitString(final String values,
+ final String delimiter) throws IllegalArgumentException {
+ if (values == null) {
+ return new String[0];
+ }
+
+ final List tokens = new ArrayList(values.length() / 10);
+ int pointer = 0;
+ int quotePointer = 0;
+ int tokenStart = 0;
+ int nextDelimiter;
+ while ((nextDelimiter = values.indexOf(delimiter, pointer)) > -1) {
+ int openingQuote = values.indexOf("\"", quotePointer);
+ int closingQuote = values.indexOf("\"", openingQuote + 1);
+ if (openingQuote > closingQuote) {
+ throw new IllegalArgumentException(
+ "Missing closing quotation mark.");
+ }
+ if (openingQuote > -1 && openingQuote < nextDelimiter
+ && closingQuote < nextDelimiter) {
+ quotePointer = ++closingQuote;
+ continue;
+ }
+ if (openingQuote < nextDelimiter && nextDelimiter < closingQuote) {
+ pointer = ++closingQuote;
+ continue;
+ }
+ // TODO: for performance, fold the trim into the splitting
+ tokens.add(values.substring(tokenStart, nextDelimiter).trim());
+ pointer = ++nextDelimiter;
+ quotePointer = pointer;
+ tokenStart = pointer;
+ }
+ tokens.add(values.substring(tokenStart).trim());
+ return (String[]) tokens.toArray(new String[tokens.size()]);
+ }
+
+ /**
+ * splits a parameter (directives or attributes) into key and value
+ *
+ * @param token
+ * @return The split string
+ * @throws IllegalArgumentException
+ */
+ public static String[] splitParameter(final String token)
+ throws IllegalArgumentException {
+ int pos = token.indexOf(":=");
+ int offset = 2;
+ if (pos < 0) {
+ pos = token.indexOf("=");
+ if (pos < 0) {
+ throw new IllegalArgumentException("Malformed parameter "
+ + token);
+ }
+ offset = 1;
+ }
+ return new String[] { token.substring(0, pos),
+ unQuote(token.substring(pos + offset, token.length())) };
+ }
+
+ public static String unQuote(final String quoted) {
+ final int len = quoted.length();
+ final int start = quoted.charAt(0) == '"' ? 1 : 0;
+ final int end = quoted.charAt(quoted.length() - 1) == '"' ? len - 1
+ : len;
+ return (start == 0 && end == len) ? quoted : quoted.substring(start,
+ end);
+ }
+
+ /**
+ * check, if the version is in the range of the version range specified by
+ * str
+ *
+ * @param version
+ * the Version to compare against the range
+ * @param str
+ * String, that describes the version range
+ * @return true, if version in range
+ */
+ public static boolean isVersionInRange(Version version, String str) {
+ // System.out.println(" VERSION CHECK: "+version.toString()+" in range "+str+"?");
+
+ // parse range
+ if (str == null || str.length() < 1) {
+ return (version.compareTo(Version.emptyVersion) > -1);
+ }
+
+ // remove "
+ if (str.startsWith("\"")) {
+ str = str.substring(1, str.length());
+ }
+ if (str.endsWith("\"")) {
+ str = str.substring(0, str.length() - 1);
+ }
+
+ final String[] bounds = splitString(str, ",");
+ if (bounds.length <= 1) {
+ // range is only an "atleast value"
+ Version v2 = new Version(str);
+ if (version.compareTo(v2) < 0) {
+ return false;
+ }
+ } else {
+ // range has lower and upper bound
+ final Version lower = new Version(bounds[0].substring(1).trim());
+ final Version upper = new Version(bounds[1].substring(0,
+ bounds[1].length() - 1).trim());
+ // check lower bound
+ if (bounds[0].startsWith("[")) {
+ if (version.compareTo(lower) < 0) {
+ return false;
+ }
+ } else {
+ // assume "("
+ if (version.compareTo(lower) <= 0) {
+ return false;
+ }
+ }
+ // check upper bound
+ if (bounds[1].endsWith("]")) {
+ if (version.compareTo(upper) > 0) {
+ return false;
+ }
+ } else {
+ // assume ")"
+ if (version.compareTo(upper) >= 0) {
+ return false;
+ }
+ }
+
+ }
+ return true;
+ }
+
/**
* transforms a string list into an array of Strings.
*

Back to the top