blob: bc8fe36ffd77eb5dcbb8a2cc16dc0ea8da3bd774 [file] [log] [blame]
/****************************************************************************
* Copyright (c) 2009 Composent, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Composent, Inc. - initial API and implementation
*****************************************************************************/
package org.eclipse.ecf.internal.examples.remoteservices.hello.consumer;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.ecf.core.IContainerFactory;
import org.eclipse.ecf.examples.remoteservices.hello.HelloMessage;
import org.eclipse.ecf.examples.remoteservices.hello.IHello;
import org.eclipse.ecf.examples.remoteservices.hello.IHelloAsync;
import org.eclipse.ecf.osgi.services.distribution.IDistributionConstants;
import org.eclipse.ecf.remoteservice.IAsyncCallback;
import org.eclipse.ecf.remoteservice.IRemoteService;
import org.eclipse.ecf.remoteservice.IRemoteServiceProxy;
import org.eclipse.ecf.remoteservice.RemoteServiceHelper;
import org.eclipse.equinox.app.IApplication;
import org.eclipse.equinox.app.IApplicationContext;
import org.eclipse.equinox.concurrent.future.IFuture;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Filter;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.util.tracker.ServiceTracker;
import org.osgi.util.tracker.ServiceTrackerCustomizer;
public class HelloConsumerApplication implements IApplication,
IDistributionConstants, ServiceTrackerCustomizer {
public static final String CONSUMER_NAME = "org.eclipse.ecf.examples.remoteservices.hello.consumer";
private BundleContext bundleContext;
private ServiceTracker containerFactoryServiceTracker;
private String containerType = "ecf.r_osgi.peer";
private final Object appLock = new Object();
private boolean done = false;
private ServiceTracker helloServiceTracker;
private ServiceRegistration discoveryListenerRegistration;
private ServiceRegistration distributionListenerRegistration;
public Object start(IApplicationContext appContext) throws Exception {
// Set bundle context (for use with service trackers)
bundleContext = Activator.getContext();
processArgs(appContext);
// Create ECF container of appropriate type. The container instance
// can be created in a variety of ways...e.g. via code like the line below,
// via the new org.eclipse.ecf.container extension point, or automatically
// upon discovery via the IProxyContainerFinder/DefaultProxyContainerFinder.
getContainerFactory().createContainer(containerType);
// Create service tracker to track IHello instances that have the 'service.imported'
// property set (as defined by OSGi 4.2 remote services spec).
helloServiceTracker = new ServiceTracker(bundleContext,
createRemoteFilter(), this);
helloServiceTracker.open();
waitForDone();
return IApplication.EXIT_OK;
}
private Filter createRemoteFilter() throws InvalidSyntaxException {
// This filter looks for IHello instances that have the
// 'service.imported' property set, as specified by OSGi 4.2
// remote services spec (Chapter 13)
return bundleContext.createFilter("(&("
+ org.osgi.framework.Constants.OBJECTCLASS + "="
+ IHello.class.getName() + ")(" + SERVICE_IMPORTED + "=*))");
}
public void stop() {
if (helloServiceTracker != null) {
helloServiceTracker.close();
helloServiceTracker = null;
}
if (containerFactoryServiceTracker != null) {
containerFactoryServiceTracker.close();
containerFactoryServiceTracker = null;
}
if (discoveryListenerRegistration != null) {
discoveryListenerRegistration.unregister();
discoveryListenerRegistration = null;
}
if (distributionListenerRegistration != null) {
distributionListenerRegistration.unregister();
distributionListenerRegistration = null;
}
this.bundleContext = null;
synchronized (appLock) {
done = true;
appLock.notifyAll();
}
}
private IContainerFactory getContainerFactory() {
if (containerFactoryServiceTracker == null) {
containerFactoryServiceTracker = new ServiceTracker(bundleContext,
IContainerFactory.class.getName(), null);
containerFactoryServiceTracker.open();
}
return (IContainerFactory) containerFactoryServiceTracker.getService();
}
private void processArgs(IApplicationContext appContext) {
String[] originalArgs = (String[]) appContext.getArguments().get(
"application.args");
if (originalArgs == null)
return;
for (int i = 0; i < originalArgs.length; i++) {
if (originalArgs[i].equals("-containerType")) {
containerType = originalArgs[i + 1];
i++;
}
}
}
private void waitForDone() {
// then just wait here
synchronized (appLock) {
while (!done) {
try {
appLock.wait();
} catch (InterruptedException e) {
// do nothing
}
}
}
}
/**
* Method called when a REMOTE IHello instance is registered.
*/
public Object addingService(ServiceReference reference) {
System.out.println("IHello service proxy being added");
// Since this reference is for a remote service,
// The service object returned is a proxy implementing the
// IHello interface
IHello proxy = (IHello) bundleContext.getService(reference);
// Call proxy synchronously. Note that this call may block or fail due to
// synchronous communication with remote service
System.out.println("STARTING remote call via proxy...");
proxy.hello(CONSUMER_NAME+" via proxy");
System.out.println("COMPLETED remote call via proxy");
System.out.println();
// Call other helloMessage method
System.out.println("STARTING remote call via proxy...");
proxy.helloMessage(new HelloMessage(CONSUMER_NAME+" via proxy","howdy"));
System.out.println("COMPLETED remote call via proxy");
System.out.println();
// If the proxy is also an instance of IHelloAsync then use
// this asynchronous interface to invoke methods asynchronously
if (proxy instanceof IHelloAsync) {
IHelloAsync helloA = (IHelloAsync) proxy;
// Create callback for use in IHelloAsync
IAsyncCallback callback = new IAsyncCallback<String>() {
public void onSuccess(String result) {
System.out.println("COMPLETED remote call with callback SUCCESS with result="+result);
System.out.println();
}
public void onFailure(Throwable t) {
System.out.println("COMPLETED remote call with callback FAILED with exception="+t);
System.out.println();
}
};
// Call asynchronously with callback
System.out.println("STARTING async remote call via callback...");
helloA.helloAsync(CONSUMER_NAME + " via async proxy with listener", callback);
System.out.println("LOCAL async invocation complete");
System.out.println();
// Call asynchronously with future
System.out.println("STARTING async remote call via future...");
IFuture future = helloA.helloAsync(CONSUMER_NAME + " via async proxy with future");
System.out.println("LOCAL async future invocation complete");
System.out.println();
try {
while (!future.isDone()) {
// do some other stuff
System.out.println("LOCAL future not yet done...so we're doing other stuff while waiting for future to be done");
Thread.sleep(200);
}
// Now it's done, so this will not block
Object result = future.get();
System.out.println("COMPLETED remote call with future SUCCEEDED with result="+result);
System.out.println();
} catch (OperationCanceledException e) {
System.out.println("COMPLETED remote call with callback CANCELLED with exception="+e);
System.out.println();
e.printStackTrace();
} catch (InterruptedException e) {
System.out.println("COMPLETED remote call with callback INTERRUPTED with exception="+e);
System.out.println();
e.printStackTrace();
}
// Call other helloMessage method
// Call asynchronously with callback
System.out.println("STARTING async remote call via callback...");
helloA.helloMessageAsync(new HelloMessage(CONSUMER_NAME + " via async proxy with listener","howdy"), callback);
System.out.println("LOCAL async invocation complete");
System.out.println();
// Call asynchronously with future
System.out.println("STARTING async remote call via future...");
future = helloA.helloMessageAsync(new HelloMessage(CONSUMER_NAME + " via async proxy with future","howdy"));
System.out.println("LOCAL async future invocation complete");
System.out.println();
try {
while (!future.isDone()) {
// do some other stuff
System.out.println("LOCAL future not yet done...so we're doing other stuff while waiting for future to be done");
Thread.sleep(200);
}
// Now it's done, so this will not block
Object result = future.get();
System.out.println("COMPLETED remote call with future SUCCEEDED with result="+result);
System.out.println();
} catch (OperationCanceledException e) {
System.out.println("COMPLETED remote call with callback CANCELLED with exception="+e);
System.out.println();
e.printStackTrace();
} catch (InterruptedException e) {
System.out.println("COMPLETED remote call with callback INTERRUPTED with exception="+e);
System.out.println();
e.printStackTrace();
}
}
// OSGi 4.2 remote service spec requires a property named 'service.imported' to be
// set to a non-null value. In the case of any ECF provider, this 'service.imported' property
// is set to the IRemoteService object associated with the remote service.
IRemoteService remoteService = (IRemoteService) reference
.getProperty(IDistributionConstants.SERVICE_IMPORTED);
Assert.isNotNull(remoteService);
// This IRemoteService instance allows allows non-blocking/asynchronous invocation of
// remote methods. This allows the client to decide (at runtime if necessary) whether
// to do synchronous/blocking calls or asynchronous/non-blocking calls.
// It's also possible to get the remote service directly from the proxy
remoteService = ((IRemoteServiceProxy) proxy).getRemoteService();
Assert.isNotNull(remoteService);
// In this case, we will make an non-blocking call and immediately get a 'future'...which is
// a placeholder for a result of the remote computation. This will not block.
System.out.println("STARTING async remote call via future...");
IFuture future = RemoteServiceHelper.futureExec(remoteService, "hello",
new Object[] { CONSUMER_NAME + " future" });
System.out.println("LOCAL async future invocation complete");
// Client can execute arbitrary code here...
try {
// This blocks until communication and computation have completed successfully
while (!future.isDone()) {
// do some other stuff
System.out.println("LOCAL future not yet done...so we're doing other stuff while waiting for future to be done");
Thread.sleep(200);
}
// Now it's done, so this will not block
Object result = future.get();
System.out.println("COMPLETED remote call with future SUCCEEDED with result="+result);
System.out.println();
} catch (Exception e) {
e.printStackTrace();
}
return proxy;
}
public void modifiedService(ServiceReference reference, Object service) {
}
public void removedService(ServiceReference reference, Object service) {
System.out.println("IHello Service proxy removed");
}
}