diff options
| author | pnehrer | 2006-07-05 02:11:18 +0000 |
|---|---|---|
| committer | pnehrer | 2006-07-05 02:11:18 +0000 |
| commit | ac7782c0e2e05c8e41ba662c98fe5cd88cc9f612 (patch) | |
| tree | 5645f0b7fe00af876a782a67c4ad6c173064439f | |
| parent | b7547bc2af999d6982bab3fc0ab91dfa07499f87 (diff) | |
| download | org.eclipse.ecf-ac7782c0e2e05c8e41ba662c98fe5cd88cc9f612.tar.gz org.eclipse.ecf-ac7782c0e2e05c8e41ba662c98fe5cd88cc9f612.tar.xz org.eclipse.ecf-ac7782c0e2e05c8e41ba662c98fe5cd88cc9f612.zip | |
Initial check-in.
35 files changed, 2301 insertions, 0 deletions
diff --git a/examples/bundles/org.eclipse.ecf.example.pubsub/.classpath b/examples/bundles/org.eclipse.ecf.example.pubsub/.classpath new file mode 100644 index 000000000..ce7393340 --- /dev/null +++ b/examples/bundles/org.eclipse.ecf.example.pubsub/.classpath @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="src" path="src"/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.4"/> + <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> + <classpathentry kind="output" path="bin"/> +</classpath> diff --git a/examples/bundles/org.eclipse.ecf.example.pubsub/.project b/examples/bundles/org.eclipse.ecf.example.pubsub/.project new file mode 100644 index 000000000..66b4c8d19 --- /dev/null +++ b/examples/bundles/org.eclipse.ecf.example.pubsub/.project @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>org.eclipse.ecf.example.pubsub</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.ManifestBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.SchemaBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.pde.PluginNature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/examples/bundles/org.eclipse.ecf.example.pubsub/.settings/org.eclipse.jdt.core.prefs b/examples/bundles/org.eclipse.ecf.example.pubsub/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..c330295c3 --- /dev/null +++ b/examples/bundles/org.eclipse.ecf.example.pubsub/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +#Tue Jul 04 17:05:21 EDT 2006 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2 +org.eclipse.jdt.core.compiler.compliance=1.4 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=warning +org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning +org.eclipse.jdt.core.compiler.source=1.3 diff --git a/examples/bundles/org.eclipse.ecf.example.pubsub/META-INF/MANIFEST.MF b/examples/bundles/org.eclipse.ecf.example.pubsub/META-INF/MANIFEST.MF new file mode 100644 index 000000000..b538315b3 --- /dev/null +++ b/examples/bundles/org.eclipse.ecf.example.pubsub/META-INF/MANIFEST.MF @@ -0,0 +1,18 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: ECF Publish/Subscribe Example Plug-in +Bundle-SymbolicName: org.eclipse.ecf.example.pubsub;singleton:=true +Bundle-Version: 1.0.0 +Bundle-Activator: org.eclipse.ecf.example.pubsub.Activator +Bundle-Vendor: Eclipse.org +Bundle-Localization: plugin +Require-Bundle: org.eclipse.ui, + org.eclipse.core.runtime, + org.eclipse.ecf;visibility:=reexport +Eclipse-AutoStart: true +Bundle-RequiredExecutionEnvironment: J2SE-1.4 +Export-Package: org.eclipse.ecf.example.pubsub, + org.eclipse.ecf.pubsub, + org.eclipse.ecf.pubsub.impl, + org.eclipse.ecf.pubsub.model, + org.eclipse.ecf.pubsub.model.impl diff --git a/examples/bundles/org.eclipse.ecf.example.pubsub/build.properties b/examples/bundles/org.eclipse.ecf.example.pubsub/build.properties new file mode 100644 index 000000000..e9863e281 --- /dev/null +++ b/examples/bundles/org.eclipse.ecf.example.pubsub/build.properties @@ -0,0 +1,5 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + plugin.xml diff --git a/examples/bundles/org.eclipse.ecf.example.pubsub/plugin.xml b/examples/bundles/org.eclipse.ecf.example.pubsub/plugin.xml new file mode 100644 index 000000000..4cc481889 --- /dev/null +++ b/examples/bundles/org.eclipse.ecf.example.pubsub/plugin.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8"?> +<?eclipse version="3.2"?> +<plugin> + <extension-point id="modelUpdater" name="Shared Model Updater" schema="schema/modelUpdater.exsd"/> + <extension + point="org.eclipse.core.runtime.adapters"> + <factory + adaptableType="org.eclipse.ecf.core.ISharedObjectContainer" + class="org.eclipse.ecf.pubsub.impl.PubSubAdapterFactory"> + <adapter type="org.eclipse.ecf.pubsub.IPublishedServiceDirectory"/> + <adapter type="org.eclipse.ecf.pubsub.IPublishedServiceRequestor"/> + </factory> + </extension> + <extension + point="org.eclipse.ui.views"> + <view + class="org.eclipse.ecf.example.pubsub.PubSubView" + id="org.eclipse.ecf.example.pubsub.publications" + name="Published Services"/> + <view + allowMultiple="true" + class="org.eclipse.ecf.example.pubsub.SubscriptionView" + id="org.eclipse.ecf.example.pubsub.subscription" + name="Subscription"/> + </extension> + <extension + point="org.eclipse.ecf.example.pubsub.modelUpdater"> + <modelUpdater + class="org.eclipse.ecf.example.pubsub.ListAppender" + id="org.eclipse.ecf.example.pubsub.ListAppender"/> + </extension> + +</plugin> diff --git a/examples/bundles/org.eclipse.ecf.example.pubsub/schema/modelUpdater.exsd b/examples/bundles/org.eclipse.ecf.example.pubsub/schema/modelUpdater.exsd new file mode 100644 index 000000000..73a13909a --- /dev/null +++ b/examples/bundles/org.eclipse.ecf.example.pubsub/schema/modelUpdater.exsd @@ -0,0 +1,117 @@ +<?xml version='1.0' encoding='UTF-8'?> +<!-- Schema file written by PDE --> +<schema targetNamespace="org.eclipse.ecf.example.pubsub"> +<annotation> + <appInfo> + <meta.schema plugin="org.eclipse.ecf.example.pubsub" id="modelUpdater" name="Shared Model Updater"/> + </appInfo> + <documentation> + [Enter description of this extension point.] + </documentation> + </annotation> + + <element name="extension"> + <complexType> + <sequence> + <element ref="modelUpdater" minOccurs="1" maxOccurs="unbounded"/> + </sequence> + <attribute name="point" type="string" use="required"> + <annotation> + <documentation> + + </documentation> + </annotation> + </attribute> + <attribute name="id" type="string"> + <annotation> + <documentation> + + </documentation> + </annotation> + </attribute> + <attribute name="name" type="string"> + <annotation> + <documentation> + + </documentation> + <appInfo> + <meta.attribute translatable="true"/> + </appInfo> + </annotation> + </attribute> + </complexType> + </element> + + <element name="modelUpdater"> + <annotation> + <appInfo> + <meta.element labelAttribute="id"/> + </appInfo> + </annotation> + <complexType> + <attribute name="id" type="string" use="required"> + <annotation> + <documentation> + + </documentation> + </annotation> + </attribute> + <attribute name="class" type="string" use="required"> + <annotation> + <documentation> + + </documentation> + <appInfo> + <meta.attribute kind="java" basedOn="org.eclipse.ecf.example.pubsub.IModelUpdater"/> + </appInfo> + </annotation> + </attribute> + </complexType> + </element> + + <annotation> + <appInfo> + <meta.section type="since"/> + </appInfo> + <documentation> + [Enter the first release in which this extension point appears.] + </documentation> + </annotation> + + <annotation> + <appInfo> + <meta.section type="examples"/> + </appInfo> + <documentation> + [Enter extension point usage example here.] + </documentation> + </annotation> + + <annotation> + <appInfo> + <meta.section type="apiInfo"/> + </appInfo> + <documentation> + [Enter API information here.] + </documentation> + </annotation> + + <annotation> + <appInfo> + <meta.section type="implementation"/> + </appInfo> + <documentation> + [Enter information about supplied implementation of this extension point.] + </documentation> + </annotation> + + <annotation> + <appInfo> + <meta.section type="copyright"/> + </appInfo> + <documentation> + + </documentation> + </annotation> + +</schema> diff --git a/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/example/pubsub/Activator.java b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/example/pubsub/Activator.java new file mode 100644 index 000000000..643da6e8d --- /dev/null +++ b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/example/pubsub/Activator.java @@ -0,0 +1,60 @@ +/** + * Copyright (c) 2006 Ecliptical Software 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: + * Ecliptical Software Inc. - initial API and implementation + */ +package org.eclipse.ecf.example.pubsub; + +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle + */ +public class Activator extends AbstractUIPlugin { + + // The plug-in ID + public static final String PLUGIN_ID = "org.eclipse.ecf.example.pubsub"; + + // The shared instance + private static Activator plugin; + + /** + * The constructor + */ + public Activator() { + plugin = this; + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext) + */ + public void start(BundleContext context) throws Exception { + super.start(context); + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext) + */ + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static Activator getDefault() { + return plugin; + } + +} diff --git a/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/example/pubsub/AppendableList.java b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/example/pubsub/AppendableList.java new file mode 100644 index 000000000..b164487c7 --- /dev/null +++ b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/example/pubsub/AppendableList.java @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2006 Ecliptical Software 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: + * Ecliptical Software Inc. - initial API and implementation + */ +package org.eclipse.ecf.example.pubsub; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.runtime.ISafeRunnable; +import org.eclipse.core.runtime.ListenerList; +import org.eclipse.core.runtime.SafeRunner; + +public class AppendableList implements Serializable { + + private static final long serialVersionUID = -5447897626712251185L; + + private transient ListenerList listeners; + + protected final List values = new ArrayList(); + + public void addListener(IAppendableListListener listener) { + getListenerList().add(listener); + } + + public void removeListener(IAppendableListListener listener) { + getListenerList().remove(listener); + } + + protected void fireAppended(final Object value) { + Object[] l = getListenerList().getListeners(); + for (int i = 0; i < l.length; ++i) { + final IAppendableListListener listener = (IAppendableListListener) l[i]; + SafeRunner.run(new ISafeRunnable() { + + public void run() throws Exception { + listener.appended(AppendableList.this, value); + } + + public void handleException(Throwable exception) { + // TODO Auto-generated method stub + + } + }); + } + } + + protected synchronized ListenerList getListenerList() { + if (listeners == null) + listeners = new ListenerList(); + + return listeners; + } + + public synchronized Object[] getValues() { + return values.toArray(); + } + + public synchronized boolean add(Object value) { + boolean result = values.add(value); + fireAppended(value); + return result; + } + + public String toString() { + return values.toString(); + } +} diff --git a/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/example/pubsub/IAppendableListListener.java b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/example/pubsub/IAppendableListListener.java new file mode 100644 index 000000000..57b21e99a --- /dev/null +++ b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/example/pubsub/IAppendableListListener.java @@ -0,0 +1,16 @@ +/** + * Copyright (c) 2006 Ecliptical Software 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: + * Ecliptical Software Inc. - initial API and implementation + */ +package org.eclipse.ecf.example.pubsub; + +public interface IAppendableListListener { + + void appended(AppendableList list, Object value); +} diff --git a/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/example/pubsub/ListAppender.java b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/example/pubsub/ListAppender.java new file mode 100644 index 000000000..b4f6c6bd0 --- /dev/null +++ b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/example/pubsub/ListAppender.java @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2006 Ecliptical Software 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: + * Ecliptical Software Inc. - initial API and implementation + */ +package org.eclipse.ecf.example.pubsub; + +import org.eclipse.ecf.pubsub.model.IModelUpdater; + +public class ListAppender implements IModelUpdater { + + public static final String ID = "org.eclipse.ecf.example.pubsub.ListAppender"; + + public void update(Object data, Object update) { + ((AppendableList) data).add(update); + } +} diff --git a/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/example/pubsub/PubSubView.java b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/example/pubsub/PubSubView.java new file mode 100644 index 000000000..d4e9f9ab2 --- /dev/null +++ b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/example/pubsub/PubSubView.java @@ -0,0 +1,270 @@ +/** + * Copyright (c) 2006 Ecliptical Software 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: + * Ecliptical Software Inc. - initial API and implementation + */ +package org.eclipse.ecf.example.pubsub; + +import java.io.IOException; +import java.util.Vector; + +import org.eclipse.ecf.core.ISharedObjectContainer; +import org.eclipse.ecf.core.SharedObjectContainerFactory; +import org.eclipse.ecf.core.SharedObjectCreateException; +import org.eclipse.ecf.core.identity.IDFactory; +import org.eclipse.ecf.core.identity.IDInstantiationException; +import org.eclipse.ecf.core.util.ECFException; +import org.eclipse.ecf.pubsub.IPublishedServiceDirectory; +import org.eclipse.ecf.pubsub.IPublishedServiceDirectoryListener; +import org.eclipse.ecf.pubsub.IPublishedServiceRequestor; +import org.eclipse.ecf.pubsub.ISubscription; +import org.eclipse.ecf.pubsub.ISubscriptionCallback; +import org.eclipse.ecf.pubsub.PublishedServiceDescriptor; +import org.eclipse.ecf.pubsub.PublishedServiceDirectoryChangeEvent; +import org.eclipse.ecf.pubsub.model.IMasterModel; +import org.eclipse.ecf.pubsub.model.SharedModelFactory; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.dialogs.ErrorDialog; +import org.eclipse.jface.dialogs.InputDialog; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerSorter; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.ui.IViewSite; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.actions.BaseSelectionListenerAction; +import org.eclipse.ui.part.ViewPart; + +public class PubSubView extends ViewPart { + + protected TableViewer viewer; + + protected MenuManager menuManager; + + protected ISharedObjectContainer container; + + private BaseSelectionListenerAction subscribeAction; + + protected TableViewer sharedListViewer; + + protected MenuManager sharedListMenuManager; + + private BaseSelectionListenerAction appendAction; + + protected final Vector sharedLists = new Vector(); + + public void init(IViewSite site) throws PartInitException { + super.init(site); + + final Action shareSomethingAction = new Action("Share something...") { + public void run() { + try { + IMasterModel sds = SharedModelFactory.getInstance().createSharedDataSource(container, IDFactory.getDefault().createGUID(), new AppendableList(), ListAppender.ID); + if (sds == null) + MessageDialog.openError(getSite().getShell(), "Error", "Could not share anything."); + else { + sharedLists.add(sds); + sharedListViewer.add(sds); + } + } catch (SharedObjectCreateException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IDInstantiationException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + }; + + shareSomethingAction.setEnabled(false); + + IMenuManager mgr = site.getActionBars().getMenuManager(); + mgr.add(new Action("Connect") { + public void run() { + try { + container = SharedObjectContainerFactory.getDefault().createSharedObjectContainer("ecf.generic.client"); + container.connect(IDFactory.getDefault().createStringID("ecftcp://localhost:3282/server"), null); + IPublishedServiceDirectory directory = (IPublishedServiceDirectory) container.getAdapter(IPublishedServiceDirectory.class); + viewer.setInput(directory); + setEnabled(false); + shareSomethingAction.setEnabled(true); + } catch (ECFException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + }); + + mgr.add(shareSomethingAction); + + menuManager = new MenuManager(); + subscribeAction = new BaseSelectionListenerAction("Subscribe") { + + public void run() { + PublishedServiceDescriptor desc = (PublishedServiceDescriptor) getStructuredSelection().getFirstElement(); + IPublishedServiceRequestor requestor = (IPublishedServiceRequestor) container.getAdapter(IPublishedServiceRequestor.class); + requestor.subscribe(desc.getContainerID(), desc.getSharedObjectID(), new SubscriptionViewOpener()); + } + + protected boolean updateSelection(IStructuredSelection selection) { + return !selection.isEmpty(); + } + }; + + subscribeAction.setEnabled(false); + menuManager.add(subscribeAction); + + sharedListMenuManager = new MenuManager(); + appendAction = new BaseSelectionListenerAction("Append...") { + + public void run() { + InputDialog dlg = new InputDialog(getSite().getShell(), "Append to Shared List", "Enter element to append:", null, null); + dlg.open(); + String value = dlg.getValue(); + if (value != null) { + IMasterModel list = (IMasterModel) getStructuredSelection().getFirstElement(); + try { + list.update(value); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + + protected boolean updateSelection(IStructuredSelection selection) { + return !selection.isEmpty(); + } + }; + + appendAction.setEnabled(false); + sharedListMenuManager.add(appendAction); + } + + public void createPartControl(Composite parent) { + Composite composite = new Composite(parent, SWT.NONE); + composite.setLayout(new GridLayout(2, true)); + + Label label = new Label(composite, SWT.NONE); + label.setText("Remote Shared Services"); + + label = new Label(composite, SWT.NONE); + label.setText("Local Shared Sample Lists"); + + viewer = new TableViewer(composite); + viewer.getTable().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + viewer.setUseHashlookup(true); + viewer.setLabelProvider(new LabelProvider()); + viewer.setContentProvider(new ContentProvider()); + viewer.setSorter(new ViewerSorter()); + viewer.addSelectionChangedListener(subscribeAction); + viewer.getControl().setMenu(menuManager.createContextMenu(viewer.getControl())); + + sharedListViewer = new TableViewer(composite); + sharedListViewer.getTable().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + sharedListViewer.setUseHashlookup(true); + sharedListViewer.setLabelProvider(new LabelProvider()); + sharedListViewer.setContentProvider(new ArrayContentProvider()); + sharedListViewer.addSelectionChangedListener(appendAction); + sharedListViewer.getControl().setMenu(sharedListMenuManager.createContextMenu(sharedListViewer.getControl())); + } + + public void setFocus() { + viewer.getControl().setFocus(); + } + + public void dispose() { + menuManager.dispose(); + + if (container != null) + container.disconnect(); + + super.dispose(); + } + + protected class ContentProvider implements IStructuredContentProvider, IPublishedServiceDirectoryListener { + + private Viewer viewer; + + public Object[] getElements(Object inputElement) { + return new Object[0]; + } + + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + this.viewer = viewer; + + if (oldInput instanceof IPublishedServiceDirectory) + ((IPublishedServiceDirectory) oldInput).removeReplicatedServiceListener(this); + + if (newInput instanceof IPublishedServiceDirectory) + ((IPublishedServiceDirectory) newInput).addReplicatedServiceListener(this); + } + + public void dispose() { + viewer = null; + } + + public void publishedServiceDirectoryChanged(final PublishedServiceDirectoryChangeEvent event) { + if (viewer instanceof TableViewer) { + Control ctrl = viewer == null ? null : viewer.getControl(); + if (ctrl != null && !ctrl.isDisposed()) + ctrl.getDisplay().asyncExec(new Runnable() { + public void run() { + TableViewer tableViewer = (TableViewer) viewer; + if (event.getKind() == PublishedServiceDirectoryChangeEvent.ADDED) + tableViewer.add(event.getReplicatedServices()); + else + tableViewer.remove(event.getReplicatedServices()); + } + }); + } + } + } + + protected class SubscriptionViewOpener implements ISubscriptionCallback { + + public void subscribed(final ISubscription subscription) { + Display.getDefault().asyncExec(new Runnable() { + public void run() { + SubscriptionView view; + try { + view = (SubscriptionView) PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().showView(SubscriptionView.VIEW_ID, subscription.getID().getName(), IWorkbenchPage.VIEW_ACTIVATE); + } catch (PartInitException e) { + ErrorDialog.openError(getSite().getShell(), "Subscription Error", "Could not create subscription view.", e.getStatus()); + return; + } + + view.setSubscription(container, subscription); + } + }); + } + + public void subscriptionFailed(final Throwable t) { + Display.getDefault().asyncExec(new Runnable() { + public void run() { + MessageDialog.openError(getSite().getShell(), "Subscription Error", t.getLocalizedMessage()); + } + }); + } + } +} diff --git a/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/example/pubsub/SubscriptionView.java b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/example/pubsub/SubscriptionView.java new file mode 100644 index 000000000..653a3e22f --- /dev/null +++ b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/example/pubsub/SubscriptionView.java @@ -0,0 +1,81 @@ +/** + * Copyright (c) 2006 Ecliptical Software 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: + * Ecliptical Software Inc. - initial API and implementation + */ +package org.eclipse.ecf.example.pubsub; + +import java.io.PrintWriter; +import java.io.StringWriter; + +import org.eclipse.ecf.core.ISharedObjectContainer; +import org.eclipse.ecf.pubsub.ISubscription; +import org.eclipse.ecf.pubsub.model.IReplicaModel; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.part.ViewPart; + +public class SubscriptionView extends ViewPart implements IAppendableListListener { + + public static final String VIEW_ID = "org.eclipse.ecf.example.pubsub.subscription"; + + protected ISubscription subscription; + + protected AppendableList model; + + protected Text text; + + public synchronized void setSubscription(ISharedObjectContainer container, ISubscription subscription) { + this.subscription = subscription; + setPartName("Subscription: " + subscription.getID()); + Object object = container.getSharedObjectManager().getSharedObject(subscription.getID()); + if (object instanceof IReplicaModel) { + Object data = ((IReplicaModel) object).getData(); + if (data instanceof AppendableList) { + model = (AppendableList) data; + model.addListener(this); + Object[] values = model.getValues(); + StringWriter buf = new StringWriter(); + PrintWriter writer = new PrintWriter(buf); + for (int i = 0; i < values.length; ++i) + writer.println(values[i]); + + writer.close(); + text.setText(buf.toString()); + } + } + } + + public void createPartControl(Composite parent) { + text = new Text(parent, SWT.WRAP | SWT.READ_ONLY); + } + + public void setFocus() { + text.setFocus(); + } + + public void dispose() { + if (model != null) + model.removeListener(this); + + if (subscription != null) + subscription.dispose(); + + super.dispose(); + } + + public synchronized void appended(AppendableList list, final Object value) { + Display.getDefault().asyncExec(new Runnable() { + public void run() { + text.append(String.valueOf(value) + System.getProperty("line.separator")); + } + }); + } +} diff --git a/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/IPublishedService.java b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/IPublishedService.java new file mode 100644 index 000000000..3c24eae9d --- /dev/null +++ b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/IPublishedService.java @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2006 Ecliptical Software 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: + * Ecliptical Software Inc. - initial API and implementation + */ +package org.eclipse.ecf.pubsub; + +import java.util.Map; + +import org.eclipse.ecf.core.IIdentifiable; +import org.eclipse.ecf.core.identity.ID; + +public interface IPublishedService extends IIdentifiable { + + Map getProperties(); + + void subscribe(ID containerID); + + void unsubscribe(ID containerID); +} diff --git a/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/IPublishedServiceDirectory.java b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/IPublishedServiceDirectory.java new file mode 100644 index 000000000..b9d68a723 --- /dev/null +++ b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/IPublishedServiceDirectory.java @@ -0,0 +1,18 @@ +/** + * Copyright (c) 2006 Ecliptical Software 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: + * Ecliptical Software Inc. - initial API and implementation + */ +package org.eclipse.ecf.pubsub; + +public interface IPublishedServiceDirectory { + + void addReplicatedServiceListener(IPublishedServiceDirectoryListener listener); + + void removeReplicatedServiceListener(IPublishedServiceDirectoryListener listener); +} diff --git a/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/IPublishedServiceDirectoryListener.java b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/IPublishedServiceDirectoryListener.java new file mode 100644 index 000000000..e4194b154 --- /dev/null +++ b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/IPublishedServiceDirectoryListener.java @@ -0,0 +1,16 @@ +/** + * Copyright (c) 2006 Ecliptical Software 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: + * Ecliptical Software Inc. - initial API and implementation + */ +package org.eclipse.ecf.pubsub; + +public interface IPublishedServiceDirectoryListener { + + void publishedServiceDirectoryChanged(PublishedServiceDirectoryChangeEvent event); +} diff --git a/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/IPublishedServiceRequestor.java b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/IPublishedServiceRequestor.java new file mode 100644 index 000000000..6d5c95a39 --- /dev/null +++ b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/IPublishedServiceRequestor.java @@ -0,0 +1,18 @@ +/** + * Copyright (c) 2006 Ecliptical Software 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: + * Ecliptical Software Inc. - initial API and implementation + */ +package org.eclipse.ecf.pubsub; + +import org.eclipse.ecf.core.identity.ID; + +public interface IPublishedServiceRequestor { + + void subscribe(ID containerID, ID sharedObjectID, ISubscriptionCallback callback); +} diff --git a/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/ISubscription.java b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/ISubscription.java new file mode 100644 index 000000000..25c3abb1e --- /dev/null +++ b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/ISubscription.java @@ -0,0 +1,21 @@ +/** + * Copyright (c) 2006 Ecliptical Software 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: + * Ecliptical Software Inc. - initial API and implementation + */ +package org.eclipse.ecf.pubsub; + +import org.eclipse.ecf.core.IIdentifiable; +import org.eclipse.ecf.core.identity.ID; + +public interface ISubscription extends IIdentifiable { + + ID getHomeContainerID(); + + void dispose(); +} diff --git a/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/ISubscriptionCallback.java b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/ISubscriptionCallback.java new file mode 100644 index 000000000..7cedc6a35 --- /dev/null +++ b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/ISubscriptionCallback.java @@ -0,0 +1,18 @@ +/** + * Copyright (c) 2006 Ecliptical Software 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: + * Ecliptical Software Inc. - initial API and implementation + */ +package org.eclipse.ecf.pubsub; + +public interface ISubscriptionCallback { + + void subscribed(ISubscription subscription); + + void subscriptionFailed(Throwable t); +} diff --git a/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/PublishedServiceDescriptor.java b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/PublishedServiceDescriptor.java new file mode 100644 index 000000000..010680a23 --- /dev/null +++ b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/PublishedServiceDescriptor.java @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2006 Ecliptical Software 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: + * Ecliptical Software Inc. - initial API and implementation + */ +package org.eclipse.ecf.pubsub; + +import java.io.Serializable; +import java.util.Map; + +import org.eclipse.ecf.core.identity.ID; + +public class PublishedServiceDescriptor implements Serializable { + + private static final long serialVersionUID = -3152226289167000325L; + + private final ID containerID; + + private final ID sharedObjectID; + + private final Map properties; + + public PublishedServiceDescriptor(ID containerID, ID sharedObjectID, Map properties) { + this.containerID = containerID; + this.sharedObjectID = sharedObjectID; + this.properties = properties; + } + + public ID getContainerID() { + return containerID; + } + + public ID getSharedObjectID() { + return sharedObjectID; + } + + public Map getProperties() { + return properties; + } + + public int hashCode() { + int c = 17; + c = 37 * c + containerID.hashCode(); + c = 37 * c + sharedObjectID.hashCode(); + c = 37 * c + properties.hashCode(); + return c; + } + + public boolean equals(Object obj) { + if (this == obj) + return true; + + if (obj == null) + return false; + + if (getClass() != obj.getClass()) + return false; + + PublishedServiceDescriptor other = (PublishedServiceDescriptor) obj; + return containerID.equals(other.containerID) && sharedObjectID.equals(other.sharedObjectID) && properties.equals(other.properties); + } + + public String toString() { + StringBuffer buf = new StringBuffer("PublishedServiceDescriptor["); + buf.append("containerID=").append(containerID).append(';'); + buf.append("sharedObjectID=").append(sharedObjectID).append(';'); + buf.append("properties=").append(properties).append(']'); + return buf.toString(); + } +} diff --git a/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/PublishedServiceDirectoryChangeEvent.java b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/PublishedServiceDirectoryChangeEvent.java new file mode 100644 index 000000000..720f7f400 --- /dev/null +++ b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/PublishedServiceDirectoryChangeEvent.java @@ -0,0 +1,67 @@ +/** + * Copyright (c) 2006 Ecliptical Software 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: + * Ecliptical Software Inc. - initial API and implementation + */ +package org.eclipse.ecf.pubsub; + +import java.util.Arrays; +import java.util.EventObject; + +public class PublishedServiceDirectoryChangeEvent extends EventObject { + + private static final long serialVersionUID = 5748843360974872790L; + + public static final int ADDED = 0; + + public static final int REMOVED = 1; + + private final int kind; + + private final PublishedServiceDescriptor[] services; + + public PublishedServiceDirectoryChangeEvent(IPublishedServiceDirectory manager, int kind, PublishedServiceDescriptor[] services) { + super(manager); + this.kind = kind; + this.services = services; + } + + public IPublishedServiceDirectory getManager() { + return (IPublishedServiceDirectory) source; + } + + public int getKind() { + return kind; + } + + public PublishedServiceDescriptor[] getReplicatedServices() { + return services; + } + + public int hashCode() { + int c = 17; + c = 37 * c + source.hashCode(); + c = 37 * c + kind; + c = 37 * c + services[0].hashCode(); + return c; + } + + public boolean equals(Object obj) { + if (this == obj) + return true; + + if (obj == null) + return false; + + if (getClass() != obj.getClass()) + return false; + + PublishedServiceDirectoryChangeEvent other = (PublishedServiceDirectoryChangeEvent) obj; + return source.equals(other.source) && kind == other.kind && Arrays.equals(services, other.services); + } +} diff --git a/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/impl/DiscoveryAgent.java b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/impl/DiscoveryAgent.java new file mode 100644 index 000000000..1b642d106 --- /dev/null +++ b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/impl/DiscoveryAgent.java @@ -0,0 +1,227 @@ +/** + * Copyright (c) 2006 Ecliptical Software 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: + * Ecliptical Software Inc. - initial API and implementation + */ +package org.eclipse.ecf.pubsub.impl; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Map; + +import org.eclipse.core.runtime.PlatformObject; +import org.eclipse.ecf.core.ISharedObject; +import org.eclipse.ecf.core.ISharedObjectConfig; +import org.eclipse.ecf.core.ISharedObjectConnector; +import org.eclipse.ecf.core.ISharedObjectContext; +import org.eclipse.ecf.core.ISharedObjectManager; +import org.eclipse.ecf.core.ReplicaSharedObjectDescription; +import org.eclipse.ecf.core.SharedObjectConnectException; +import org.eclipse.ecf.core.SharedObjectDisconnectException; +import org.eclipse.ecf.core.SharedObjectInitException; +import org.eclipse.ecf.core.events.IContainerConnectedEvent; +import org.eclipse.ecf.core.events.IContainerDisconnectedEvent; +import org.eclipse.ecf.core.events.ISharedObjectActivatedEvent; +import org.eclipse.ecf.core.events.ISharedObjectDeactivatedEvent; +import org.eclipse.ecf.core.events.ISharedObjectMessageEvent; +import org.eclipse.ecf.core.identity.ID; +import org.eclipse.ecf.core.identity.IDFactory; +import org.eclipse.ecf.core.identity.IDInstantiationException; +import org.eclipse.ecf.core.util.Event; +import org.eclipse.ecf.core.util.QueueException; +import org.eclipse.ecf.pubsub.IPublishedService; +import org.eclipse.ecf.pubsub.PublishedServiceDescriptor; + +public class DiscoveryAgent extends PlatformObject implements ISharedObject { + + protected ISharedObjectConfig config; + + public void init(ISharedObjectConfig config) throws SharedObjectInitException { + this.config = config; + } + + public void handleEvent(Event event) { + if (event instanceof ISharedObjectActivatedEvent) { + ISharedObjectActivatedEvent e = (ISharedObjectActivatedEvent) event; + if (e.getActivatedID().equals(config.getSharedObjectID())) + activated(); + else + activated(e.getActivatedID()); + } else if (event instanceof ISharedObjectDeactivatedEvent) { + ISharedObjectDeactivatedEvent e = (ISharedObjectDeactivatedEvent) event; + if (e.getDeactivatedID().equals(config.getSharedObjectID())) + deactivated(); + else + deactivated(e.getDeactivatedID()); + } else if (event instanceof IContainerConnectedEvent) { + IContainerConnectedEvent e = (IContainerConnectedEvent) event; + if (e.getTargetID().equals(e.getLocalContainerID())) + connected(); + else + connected(e.getTargetID()); + } else if (event instanceof IContainerDisconnectedEvent) { + IContainerDisconnectedEvent e = (IContainerDisconnectedEvent) event; + if (e.getTargetID().equals(e.getLocalContainerID())) + disconnected(); + else + disconnected(e.getTargetID()); + } else if (event instanceof ISharedObjectMessageEvent) + received((ISharedObjectMessageEvent) event); + } + + protected boolean isConnected() { + return config.getContext().getConnectedID() != null; + } + + protected boolean isPrimary() { + return config.getContext().getLocalContainerID().equals(config.getHomeContainerID()); + } + + protected void activated(ID sharedObjectID) { + if (isPrimary()) + return; + + ISharedObjectContext ctx = config.getContext(); + Object object = ctx.getSharedObjectManager().getSharedObject(sharedObjectID); + if (object instanceof IPublishedService) { + IPublishedService svc = (IPublishedService) object; + Map props = svc.getProperties(); + PublishedServiceDescriptor desc = new PublishedServiceDescriptor(ctx.getLocalContainerID(), sharedObjectID, props); + try { + ctx.sendMessage(config.getHomeContainerID(), new DiscoveryMessage(DiscoveryMessage.ADDED, desc)); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + + protected void activated() { + if (isConnected()) + connected(); + } + + protected void deactivated(ID sharedObjectID) { + if (isPrimary()) + return; + + ISharedObjectContext ctx = config.getContext(); + Object object = ctx.getSharedObjectManager().getSharedObject(sharedObjectID); + if (object instanceof IPublishedService) { + IPublishedService svc = (IPublishedService) object; + Map props = svc.getProperties(); + PublishedServiceDescriptor desc = new PublishedServiceDescriptor(ctx.getLocalContainerID(), sharedObjectID, props); + try { + ctx.sendMessage(config.getHomeContainerID(), new DiscoveryMessage(DiscoveryMessage.REMOVED, desc)); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + + protected void deactivated() { + if (isPrimary() && isConnected()) + try { + config.getContext().sendDispose(null); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + protected void connected(ID containerID) { + if (isPrimary()) + try { + config.getContext().sendCreate(containerID, new ReplicaSharedObjectDescription(getClass(), config.getSharedObjectID())); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + protected void connected() { + if (isPrimary()) { + try { + config.getContext().sendCreate(null, new ReplicaSharedObjectDescription(getClass(), config.getSharedObjectID())); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } else { + ArrayList published = new ArrayList(); + ISharedObjectContext ctx = config.getContext(); + ISharedObjectManager mgr = ctx.getSharedObjectManager(); + ID[] ids = mgr.getSharedObjectIDs(); + ID containerID = ctx.getLocalContainerID(); + for (int i = 0; i < ids.length; ++i) { + Object object = mgr.getSharedObject(ids[i]); + if (object instanceof IPublishedService) { + IPublishedService svc = (IPublishedService) object; + Map props = svc.getProperties(); + published.add(new PublishedServiceDescriptor(containerID, ids[i], props)); + } + } + + if (published.isEmpty()) + return; + + PublishedServiceDescriptor[] descriptors = new PublishedServiceDescriptor[published.size()]; + published.toArray(descriptors); + try { + ctx.sendMessage(config.getHomeContainerID(), new DiscoveryMessage(DiscoveryMessage.ADDED, descriptors)); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + + protected void disconnected(ID containerID) { + if (containerID.equals(config.getHomeContainerID())) + config.getContext().getSharedObjectManager().removeSharedObject(config.getSharedObjectID()); + } + + protected void disconnected() { + config.getContext().getSharedObjectManager().removeSharedObject(config.getSharedObjectID()); + } + + protected void received(ISharedObjectMessageEvent event) { + if (!(event.getData() instanceof DiscoveryMessage)) + return; + + try { + ID directoryID = IDFactory.getDefault().createStringID(PublishedServiceDirectory.SHARED_OBJECT_ID); + ISharedObjectManager mgr = config.getContext().getSharedObjectManager(); + ISharedObjectConnector conn = mgr.connectSharedObjects(config.getSharedObjectID(), new ID[] { directoryID }); + conn.enqueue(event); + mgr.disconnectSharedObjects(conn); + } catch (IDInstantiationException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (SharedObjectConnectException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (QueueException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (SharedObjectDisconnectException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + public void handleEvents(Event[] events) { + for (int i = 0; i < events.length; ++i) + handleEvent(events[i]); + } + + public void dispose(ID containerID) { + config = null; + } +} diff --git a/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/impl/DiscoveryMessage.java b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/impl/DiscoveryMessage.java new file mode 100644 index 000000000..b226f7f51 --- /dev/null +++ b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/impl/DiscoveryMessage.java @@ -0,0 +1,67 @@ +/** + * Copyright (c) 2006 Ecliptical Software 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: + * Ecliptical Software Inc. - initial API and implementation + */ +package org.eclipse.ecf.pubsub.impl; + +import java.io.Serializable; +import java.util.Arrays; + +import org.eclipse.ecf.pubsub.PublishedServiceDescriptor; + +public class DiscoveryMessage implements Serializable { + + private static final long serialVersionUID = 2321101436711728754L; + + public static final int ADDED = 0; + + public static final int REMOVED = 1; + + private final int kind; + + private final PublishedServiceDescriptor[] descriptors; + + public DiscoveryMessage(int kind, PublishedServiceDescriptor[] descriptors) { + this.kind = kind; + this.descriptors = descriptors; + } + + public DiscoveryMessage(int kind, PublishedServiceDescriptor descriptor) { + this(kind, new PublishedServiceDescriptor[] { descriptor }); + } + + public int getKind() { + return kind; + } + + public PublishedServiceDescriptor[] getDescriptors() { + return descriptors; + } + + public int hashCode() { + int c = 17; + c = 37 * c + kind; + c = 37 * c + descriptors[0].hashCode(); + return c; + } + + public boolean equals(Object obj) { + if (this == obj) + return true; + + if (obj == null) + return false; + + if (getClass() != obj.getClass()) + return false; + + DiscoveryMessage other = (DiscoveryMessage) obj; + return kind == other.kind && Arrays.equals(descriptors, other.descriptors); + } +}
\ No newline at end of file diff --git a/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/impl/PubSubAdapterFactory.java b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/impl/PubSubAdapterFactory.java new file mode 100644 index 000000000..88b965b88 --- /dev/null +++ b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/impl/PubSubAdapterFactory.java @@ -0,0 +1,78 @@ +/** + * Copyright (c) 2006 Ecliptical Software 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: + * Ecliptical Software Inc. - initial API and implementation + */ +package org.eclipse.ecf.pubsub.impl; + +import org.eclipse.core.runtime.IAdapterFactory; +import org.eclipse.ecf.core.ISharedObjectContainer; +import org.eclipse.ecf.core.ISharedObjectManager; +import org.eclipse.ecf.core.SharedObjectCreateException; +import org.eclipse.ecf.core.SharedObjectDescription; +import org.eclipse.ecf.core.identity.ID; +import org.eclipse.ecf.core.identity.IDFactory; +import org.eclipse.ecf.core.identity.IDInstantiationException; +import org.eclipse.ecf.pubsub.IPublishedServiceDirectory; +import org.eclipse.ecf.pubsub.IPublishedServiceRequestor; + +public class PubSubAdapterFactory implements IAdapterFactory { + + private static final Class[] ADAPTERS = { IPublishedServiceDirectory.class, IPublishedServiceRequestor.class }; + + public Object getAdapter(Object adaptableObject, Class adapterType) { + if (!(adaptableObject instanceof ISharedObjectContainer)) + return null; + + if (IPublishedServiceDirectory.class.isAssignableFrom(adapterType)) + return getDirectory((ISharedObjectContainer) adaptableObject); + + if (IPublishedServiceRequestor.class.isAssignableFrom(adapterType)) + return getRequestor((ISharedObjectContainer) adaptableObject); + + return null; + } + + protected IPublishedServiceDirectory getDirectory(ISharedObjectContainer container) { + ID directoryID; + try { + directoryID = IDFactory.getDefault().createStringID(PublishedServiceDirectory.SHARED_OBJECT_ID); + } catch (IDInstantiationException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return null; + } + + final ISharedObjectManager mgr = container.getSharedObjectManager(); + IPublishedServiceDirectory directory = (IPublishedServiceDirectory) mgr.getSharedObject(directoryID); + if (directory != null) + return directory; + + try { + SharedObjectDescription desc = createDirectoryDescription(directoryID); + mgr.createSharedObject(desc); + return (IPublishedServiceDirectory) mgr.getSharedObject(directoryID); + } catch (SharedObjectCreateException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return null; + } + } + + protected SharedObjectDescription createDirectoryDescription(ID directoryID) { + return new SharedObjectDescription(PublishedServiceDirectory.class, directoryID, null); + } + + protected IPublishedServiceRequestor getRequestor(ISharedObjectContainer container) { + return new ServiceRequestor(container.getSharedObjectManager()); + } + + public Class[] getAdapterList() { + return ADAPTERS; + } +} diff --git a/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/impl/PublishedServiceDirectory.java b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/impl/PublishedServiceDirectory.java new file mode 100644 index 000000000..ed28700ab --- /dev/null +++ b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/impl/PublishedServiceDirectory.java @@ -0,0 +1,189 @@ +/** + * Copyright (c) 2006 Ecliptical Software 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: + * Ecliptical Software Inc. - initial API and implementation + */ +package org.eclipse.ecf.pubsub.impl; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; + +import org.eclipse.core.runtime.ISafeRunnable; +import org.eclipse.core.runtime.ListenerList; +import org.eclipse.core.runtime.PlatformObject; +import org.eclipse.core.runtime.SafeRunner; +import org.eclipse.ecf.core.ISharedObject; +import org.eclipse.ecf.core.ISharedObjectConfig; +import org.eclipse.ecf.core.ISharedObjectManager; +import org.eclipse.ecf.core.SharedObjectDescription; +import org.eclipse.ecf.core.SharedObjectInitException; +import org.eclipse.ecf.core.events.IContainerDisconnectedEvent; +import org.eclipse.ecf.core.events.ISharedObjectActivatedEvent; +import org.eclipse.ecf.core.events.ISharedObjectDeactivatedEvent; +import org.eclipse.ecf.core.events.ISharedObjectMessageEvent; +import org.eclipse.ecf.core.identity.ID; +import org.eclipse.ecf.core.identity.IDFactory; +import org.eclipse.ecf.core.util.ECFException; +import org.eclipse.ecf.core.util.Event; +import org.eclipse.ecf.pubsub.IPublishedServiceDirectory; +import org.eclipse.ecf.pubsub.IPublishedServiceDirectoryListener; +import org.eclipse.ecf.pubsub.PublishedServiceDescriptor; +import org.eclipse.ecf.pubsub.PublishedServiceDirectoryChangeEvent; + +public class PublishedServiceDirectory extends PlatformObject implements ISharedObject, IPublishedServiceDirectory { + + protected static final String SHARED_OBJECT_ID = IPublishedServiceDirectory.class.getName(); + + protected ISharedObjectConfig config; + + private final ListenerList listeners = new ListenerList(); + + private final Map services = new HashMap(); + + private ID discoveryAgentID; + + public synchronized void addReplicatedServiceListener(final IPublishedServiceDirectoryListener listener) { + listeners.add(listener); + PublishedServiceDescriptor[] buf = new PublishedServiceDescriptor[services.values().size()]; + services.values().toArray(buf); + final PublishedServiceDirectoryChangeEvent event = new PublishedServiceDirectoryChangeEvent(this, PublishedServiceDirectoryChangeEvent.ADDED, buf); + SafeRunner.run(new ISafeRunnable() { + + public void run() throws Exception { + listener.publishedServiceDirectoryChanged(event); + } + + public void handleException(Throwable exception) { + // TODO Auto-generated method stub + + } + }); + } + + public void removeReplicatedServiceListener(IPublishedServiceDirectoryListener listener) { + listeners.remove(listener); + } + + protected void fireServiceChangedEvent(final PublishedServiceDirectoryChangeEvent event) { + Object[] l = listeners.getListeners(); + for (int i = 0; i < l.length; ++i) { + final IPublishedServiceDirectoryListener listener = (IPublishedServiceDirectoryListener) l[i]; + SafeRunner.run(new ISafeRunnable() { + + public void run() throws Exception { + listener.publishedServiceDirectoryChanged(event); + } + + public void handleException(Throwable exception) { + // TODO Auto-generated method stub + + } + }); + } + } + + public void init(ISharedObjectConfig config) throws SharedObjectInitException { + this.config = config; + } + + public void handleEvent(Event event) { + if (event instanceof ISharedObjectActivatedEvent) + activated(((ISharedObjectActivatedEvent) event).getActivatedID()); + else if (event instanceof ISharedObjectDeactivatedEvent) + deactivated(((ISharedObjectDeactivatedEvent) event).getDeactivatedID()); + else if (event instanceof ISharedObjectMessageEvent) + received((ISharedObjectMessageEvent) event); + else if (event instanceof IContainerDisconnectedEvent) + disconnected((IContainerDisconnectedEvent) event); + } + + protected void activated(final ID sharedObjectID) { + if (sharedObjectID.equals(config.getSharedObjectID())) { + ISharedObjectManager mgr = config.getContext().getSharedObjectManager(); + if (discoveryAgentID == null) { + try { + discoveryAgentID = IDFactory.getDefault().createGUID(); + mgr.createSharedObject(new SharedObjectDescription(DiscoveryAgent.class, discoveryAgentID, null)); + } catch (ECFException e) { + // TODO Log me! + e.printStackTrace(); + } + } + } + } + + protected void deactivated(ID sharedObjectID) { + if (sharedObjectID.equals(config.getSharedObjectID())) { + if (discoveryAgentID != null) { + config.getContext().getSharedObjectManager().removeSharedObject(discoveryAgentID); + discoveryAgentID = null; + } + } + } + + protected void disconnected(IContainerDisconnectedEvent event) { + ID containerID = event.getTargetID(); + if (!containerID.equals(event.getLocalContainerID())) { + synchronized (this) { + Collection values = (Collection) services.remove(event.getTargetID()); + if (values != null) { + PublishedServiceDescriptor[] buf = new PublishedServiceDescriptor[values.size()]; + values.toArray(buf); + fireServiceChangedEvent(new PublishedServiceDirectoryChangeEvent(this, PublishedServiceDirectoryChangeEvent.REMOVED, buf)); + } + } + } + } + + protected void received(ISharedObjectMessageEvent event) { + Object data = event.getData(); + if (!(data instanceof DiscoveryMessage)) + return; + + DiscoveryMessage msg = (DiscoveryMessage) event.getData(); + PublishedServiceDescriptor[] descriptors = msg.getDescriptors(); + + synchronized (this) { + ID containerID = event.getRemoteContainerID(); + Collection values = (Collection) services.get(containerID); + if (values == null) { + values = new HashSet(); + services.put(containerID, values); + } + + if (msg.getKind() == DiscoveryMessage.ADDED) { + values.addAll(Arrays.asList(descriptors)); + } else { + values.removeAll(Arrays.asList(descriptors)); + if (values.isEmpty()) + services.remove(containerID); + } + + int kind = msg.getKind() == DiscoveryMessage.ADDED ? PublishedServiceDirectoryChangeEvent.ADDED : PublishedServiceDirectoryChangeEvent.REMOVED; + fireServiceChangedEvent(new PublishedServiceDirectoryChangeEvent(this, kind, descriptors)); + } + } + + public void handleEvents(Event[] events) { + for (int i = 0; i < events.length; ++i) + handleEvent(events[i]); + } + + public void dispose(ID containerID) { + listeners.clear(); + + synchronized (this) { + services.clear(); + } + + config = null; + } +} diff --git a/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/impl/ReplicatedServiceDiscoveryEvent.java b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/impl/ReplicatedServiceDiscoveryEvent.java new file mode 100644 index 000000000..ad454981f --- /dev/null +++ b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/impl/ReplicatedServiceDiscoveryEvent.java @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2006 Ecliptical Software 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: + * Ecliptical Software Inc. - initial API and implementation + */ +package org.eclipse.ecf.pubsub.impl; + +import java.util.Arrays; + +import org.eclipse.ecf.core.identity.ID; +import org.eclipse.ecf.core.util.Event; + +public class ReplicatedServiceDiscoveryEvent implements Event { + + private static final long serialVersionUID = 1848459358595071814L; + + public static final int ADDED = 0; + + public static final int REMOVED = 1; + + private final int kind; + + private final ID containerID; + + private final ID[] sharedObjectIDs; + + public ReplicatedServiceDiscoveryEvent(int kind, ID containerID, ID[] sharedObjectIDs) { + this.kind = kind; + this.containerID = containerID; + this.sharedObjectIDs = sharedObjectIDs; + } + + public int getKind() { + return kind; + } + + public ID getContainerID() { + return containerID; + } + + public ID[] getSharedObjectIDs() { + return sharedObjectIDs; + } + + public int hashCode() { + int c = 17; + c = 37 * c + kind; + c = 37 * c + containerID.hashCode(); + c = 37 * c + sharedObjectIDs[0].hashCode(); + return c; + } + + public boolean equals(Object obj) { + if (this == obj) + return true; + + if (obj == null) + return false; + + if (getClass() != obj.getClass()) + return false; + + ReplicatedServiceDiscoveryEvent other = (ReplicatedServiceDiscoveryEvent) obj; + return kind == other.kind && containerID.equals(other.containerID) && Arrays.equals(sharedObjectIDs, other.sharedObjectIDs); + } +} diff --git a/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/impl/ServiceRequestor.java b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/impl/ServiceRequestor.java new file mode 100644 index 000000000..de0502ba0 --- /dev/null +++ b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/impl/ServiceRequestor.java @@ -0,0 +1,60 @@ +/** + * Copyright (c) 2006 Ecliptical Software 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: + * Ecliptical Software Inc. - initial API and implementation + */ +package org.eclipse.ecf.pubsub.impl; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.ecf.core.ISharedObjectManager; +import org.eclipse.ecf.core.SharedObjectCreateException; +import org.eclipse.ecf.core.SharedObjectDescription; +import org.eclipse.ecf.core.identity.ID; +import org.eclipse.ecf.core.identity.IDFactory; +import org.eclipse.ecf.core.identity.IDInstantiationException; +import org.eclipse.ecf.pubsub.IPublishedServiceRequestor; +import org.eclipse.ecf.pubsub.ISubscriptionCallback; + +public class ServiceRequestor implements IPublishedServiceRequestor { + + protected final ISharedObjectManager mgr; + + public ServiceRequestor(ISharedObjectManager mgr) { + this.mgr = mgr; + } + + public void subscribe(ID containerID, ID sharedObjectID, ISubscriptionCallback callback) { + if (containerID == null || sharedObjectID == null || callback == null) + throw new IllegalArgumentException(); + + try { + mgr.createSharedObject(createSubscriptionDescription(containerID, sharedObjectID, callback)); + } catch (SharedObjectCreateException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + protected SharedObjectDescription createSubscriptionDescription(ID containerID, ID sharedObjectID, ISubscriptionCallback callback) { + Map props = new HashMap(3); + props.put(SubscriptionAgent.CONTAINER_ID_KEY, containerID); + props.put(SubscriptionAgent.SHARED_OBJECT_ID_KEY, sharedObjectID); + props.put(SubscriptionAgent.CALLBACK_KEY, callback); + ID id; + try { + id = IDFactory.getDefault().createGUID(); + } catch (IDInstantiationException e) { + // TODO handle this! + throw new RuntimeException(e); + } + + return new SharedObjectDescription(SubscriptionAgent.class, id, props); + } +} diff --git a/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/impl/SubscriptionAgent.java b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/impl/SubscriptionAgent.java new file mode 100644 index 000000000..7e7902aa5 --- /dev/null +++ b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/impl/SubscriptionAgent.java @@ -0,0 +1,213 @@ +/** + * Copyright (c) 2006 Ecliptical Software 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: + * Ecliptical Software Inc. - initial API and implementation + */ +package org.eclipse.ecf.pubsub.impl; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.core.runtime.PlatformObject; +import org.eclipse.ecf.core.ISharedObject; +import org.eclipse.ecf.core.ISharedObjectConfig; +import org.eclipse.ecf.core.ISharedObjectContext; +import org.eclipse.ecf.core.ISharedObjectManager; +import org.eclipse.ecf.core.ReplicaSharedObjectDescription; +import org.eclipse.ecf.core.SharedObjectInitException; +import org.eclipse.ecf.core.events.IContainerDisconnectedEvent; +import org.eclipse.ecf.core.events.ISharedObjectActivatedEvent; +import org.eclipse.ecf.core.events.ISharedObjectCreateResponseEvent; +import org.eclipse.ecf.core.events.ISharedObjectDeactivatedEvent; +import org.eclipse.ecf.core.identity.ID; +import org.eclipse.ecf.core.util.Event; +import org.eclipse.ecf.pubsub.IPublishedService; +import org.eclipse.ecf.pubsub.ISubscription; +import org.eclipse.ecf.pubsub.ISubscriptionCallback; + +public class SubscriptionAgent extends PlatformObject implements ISharedObject { + + protected static final Object CONTAINER_ID_KEY = new Integer(0); + + protected static final Object SHARED_OBJECT_ID_KEY = new Integer(1); + + protected static final Object CALLBACK_KEY = new Integer(2); + + protected ISharedObjectConfig config; + + protected ID containerID; + + protected ID sharedObjectID; + + protected ISubscriptionCallback callback; + + protected boolean subscribed; + + protected boolean disposed; + + public void init(ISharedObjectConfig config) throws SharedObjectInitException { + this.config = config; + Map props = config.getProperties(); + + if (isPrimary()) { + containerID = (ID) props.get(CONTAINER_ID_KEY); + if (containerID == null) + throw new SharedObjectInitException("containerID is required"); + + callback = (ISubscriptionCallback) props.get(CALLBACK_KEY); + if (callback == null) + throw new SharedObjectInitException("callback is required"); + } + + sharedObjectID = (ID) props.get(SHARED_OBJECT_ID_KEY); + if (sharedObjectID == null) + throw new SharedObjectInitException("sharedObjectID is required"); + } + + public void handleEvent(Event event) { + if (event instanceof ISharedObjectActivatedEvent) { + ISharedObjectActivatedEvent e = (ISharedObjectActivatedEvent) event; + if (e.getActivatedID().equals(config.getSharedObjectID())) + activated(); + else + activated(e.getActivatedID()); + } else if (event instanceof ISharedObjectDeactivatedEvent) { + ISharedObjectDeactivatedEvent e = (ISharedObjectDeactivatedEvent) event; + if (e.getDeactivatedID().equals(config.getSharedObjectID())) + deactivated(); + } else if (event instanceof IContainerDisconnectedEvent) { + IContainerDisconnectedEvent e = (IContainerDisconnectedEvent) event; + if (e.getTargetID().equals(e.getLocalContainerID())) + disconnected(); + else + disconnected(e.getTargetID()); + } else if (event instanceof ISharedObjectCreateResponseEvent) + received((ISharedObjectCreateResponseEvent) event); + } + + protected boolean isPrimary() { + return config.getContext().getLocalContainerID().equals(config.getHomeContainerID()); + } + + protected void activated() { + ISharedObjectContext ctx = config.getContext(); + if (isPrimary()) { + try { + ctx.sendCreate(containerID, createReplicaDescription()); + // TODO set timer to time out if no response received within some bound + } catch (IOException e) { + callback.subscriptionFailed(e); + ctx.getSharedObjectManager().removeSharedObject(config.getSharedObjectID()); + } + + return; + } + + ISharedObjectManager mgr = ctx.getSharedObjectManager(); + ISharedObject so = mgr.getSharedObject(sharedObjectID); + try { + ID homeContainerID = config.getHomeContainerID(); + if (so instanceof IPublishedService) { + IPublishedService svc = (IPublishedService) so; + svc.subscribe(homeContainerID); + subscribed = true; + } else { + ctx.sendCreateResponse(homeContainerID, new IllegalArgumentException("Not an IPublishedService."), -1); + } + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + + ctx.getSharedObjectManager().removeSharedObject(config.getSharedObjectID()); + } + } + + protected void activated(ID sharedObjectID) { + if (isPrimary() && sharedObjectID.equals(this.sharedObjectID)) + callback.subscribed(new Subscription()); + } + + protected void deactivated() { + if (isPrimary()) { + synchronized (this) { + disposed = true; + } + + return; + } + + if (subscribed) { + ISharedObject so = config.getContext().getSharedObjectManager().getSharedObject(sharedObjectID); + if (so instanceof IPublishedService) { + IPublishedService svc = (IPublishedService) so; + svc.unsubscribe(config.getHomeContainerID()); + subscribed = false; + } + } + } + + protected void disconnected() { + config.getContext().getSharedObjectManager().removeSharedObject(config.getSharedObjectID()); + } + + protected void disconnected(ID containerID) { + if (containerID.equals(config.getHomeContainerID()) || containerID.equals(this.containerID)) + config.getContext().getSharedObjectManager().removeSharedObject(config.getSharedObjectID()); + } + + protected void received(ISharedObjectCreateResponseEvent e) { + if (e.getRemoteContainerID().equals(containerID) && e.getSenderSharedObjectID().equals(config.getSharedObjectID())) + callback.subscriptionFailed(e.getException()); + } + + protected ReplicaSharedObjectDescription createReplicaDescription() { + Map props = new HashMap(1); + props.put(SHARED_OBJECT_ID_KEY, sharedObjectID); + return new ReplicaSharedObjectDescription(getClass(), config.getSharedObjectID(), config.getHomeContainerID(), props); + } + + public void handleEvents(Event[] events) { + for (int i = 0; i < events.length; ++i) + handleEvent(events[i]); + } + + public void dispose(ID containerID) { + config = null; + } + + protected class Subscription implements ISubscription { + + public ID getID() { + return sharedObjectID; + } + + public ID getHomeContainerID() { + return containerID; + } + + public void dispose() { + synchronized (SubscriptionAgent.this) { + if (disposed) + return; + + disposed = true; + } + + ISharedObjectContext ctx = config.getContext(); + try { + ctx.sendDispose(containerID); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + ctx.getSharedObjectManager().removeSharedObject(config.getSharedObjectID()); + } + } +} diff --git a/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/model/IMasterModel.java b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/model/IMasterModel.java new file mode 100644 index 000000000..54cca81bf --- /dev/null +++ b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/model/IMasterModel.java @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2006 Ecliptical Software 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: + * Ecliptical Software Inc. - initial API and implementation + */ +package org.eclipse.ecf.pubsub.model; + +import java.io.IOException; + +import org.eclipse.ecf.pubsub.IPublishedService; + +public interface IMasterModel extends IPublishedService { + + void update(Object data) throws IOException; +} diff --git a/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/model/IModelUpdater.java b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/model/IModelUpdater.java new file mode 100644 index 000000000..b984cb5cc --- /dev/null +++ b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/model/IModelUpdater.java @@ -0,0 +1,16 @@ +/** + * Copyright (c) 2006 Ecliptical Software 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: + * Ecliptical Software Inc. - initial API and implementation + */ +package org.eclipse.ecf.pubsub.model; + +public interface IModelUpdater { + + void update(Object data, Object update); +} diff --git a/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/model/IReplicaModel.java b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/model/IReplicaModel.java new file mode 100644 index 000000000..af2130077 --- /dev/null +++ b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/model/IReplicaModel.java @@ -0,0 +1,16 @@ +/** + * Copyright (c) 2006 Ecliptical Software 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: + * Ecliptical Software Inc. - initial API and implementation + */ +package org.eclipse.ecf.pubsub.model; + +public interface IReplicaModel { + + Object getData(); +} diff --git a/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/model/SharedModelFactory.java b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/model/SharedModelFactory.java new file mode 100644 index 000000000..bce726cd6 --- /dev/null +++ b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/model/SharedModelFactory.java @@ -0,0 +1,90 @@ +/** + * Copyright (c) 2006 Ecliptical Software 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: + * Ecliptical Software Inc. - initial API and implementation + */ +package org.eclipse.ecf.pubsub.model; + +import java.util.HashMap; + +import org.eclipse.ecf.core.IContainerListener; +import org.eclipse.ecf.core.ISharedObjectContainer; +import org.eclipse.ecf.core.ISharedObjectManager; +import org.eclipse.ecf.core.ReplicaSharedObjectDescription; +import org.eclipse.ecf.core.SharedObjectCreateException; +import org.eclipse.ecf.core.SharedObjectDescription; +import org.eclipse.ecf.core.events.IContainerEvent; +import org.eclipse.ecf.core.events.ISharedObjectActivatedEvent; +import org.eclipse.ecf.core.identity.ID; +import org.eclipse.ecf.pubsub.model.impl.AgentBase; +import org.eclipse.ecf.pubsub.model.impl.LocalAgent; + +public class SharedModelFactory { + + protected static final Object INITIAL_DATA_KEY = AgentBase.INITIAL_DATA_KEY; + + protected static final Object MODEL_UPDATER_KEY = AgentBase.MODEL_UPDATER_KEY; + + protected static final long DEFAULT_CREATION_TIMEOUT = 5000; + + private static final SharedModelFactory INSTANCE = new SharedModelFactory(); + + private SharedModelFactory() { + // no public instantiation + } + + public static SharedModelFactory getInstance() { + return INSTANCE; + } + + public IMasterModel createSharedDataSource(ISharedObjectContainer container, final ID id, Object data, String updaterID) throws SharedObjectCreateException { + final ISharedObjectManager mgr = container.getSharedObjectManager(); + final Object[] result = new Object[1]; + final Object monitor = new Object(); + IContainerListener listener = new IContainerListener() { + public void handleEvent(IContainerEvent event) { + if (event instanceof ISharedObjectActivatedEvent) { + ISharedObjectActivatedEvent e = (ISharedObjectActivatedEvent) event; + if (e.getActivatedID().equals(id)) { + result[0] = mgr.getSharedObject(id); + synchronized (monitor) { + monitor.notify(); + } + } + } + } + }; + + try { + container.addListener(listener, null); + SharedObjectDescription desc = createLocalAgentDescription(id, container.getID(), data, updaterID); + synchronized (monitor) { + mgr.createSharedObject(desc); + if (result[0] == null) + monitor.wait(getCreationTimeout()); + } + } catch (InterruptedException e) { + throw new SharedObjectCreateException(e); + } finally { + container.removeListener(listener); + } + + return (IMasterModel) result[0]; + } + + protected long getCreationTimeout() { + return DEFAULT_CREATION_TIMEOUT; + } + + protected SharedObjectDescription createLocalAgentDescription(ID sharedObjectID, ID homeContainerID, Object data, String updaterID) { + HashMap props = new HashMap(2); + props.put(INITIAL_DATA_KEY, data); + props.put(MODEL_UPDATER_KEY, updaterID); + return new ReplicaSharedObjectDescription(LocalAgent.class, sharedObjectID, homeContainerID, props); + } +} diff --git a/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/model/impl/AgentBase.java b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/model/impl/AgentBase.java new file mode 100644 index 000000000..85d86e319 --- /dev/null +++ b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/model/impl/AgentBase.java @@ -0,0 +1,158 @@ +/** + * Copyright (c) 2006 Ecliptical Software 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: + * Ecliptical Software Inc. - initial API and implementation + */ +package org.eclipse.ecf.pubsub.model.impl; + +import java.util.Map; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtensionRegistry; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.PlatformObject; +import org.eclipse.ecf.core.IIdentifiable; +import org.eclipse.ecf.core.ISharedObject; +import org.eclipse.ecf.core.ISharedObjectConfig; +import org.eclipse.ecf.core.SharedObjectInitException; +import org.eclipse.ecf.core.events.IContainerConnectedEvent; +import org.eclipse.ecf.core.events.IContainerDisconnectedEvent; +import org.eclipse.ecf.core.events.ISharedObjectActivatedEvent; +import org.eclipse.ecf.core.events.ISharedObjectDeactivatedEvent; +import org.eclipse.ecf.core.events.ISharedObjectMessageEvent; +import org.eclipse.ecf.core.identity.ID; +import org.eclipse.ecf.core.util.Event; +import org.eclipse.ecf.pubsub.model.IModelUpdater; + +public abstract class AgentBase extends PlatformObject implements ISharedObject, IIdentifiable { + + public static final Object INITIAL_DATA_KEY = new Integer(0); + + public static final Object MODEL_UPDATER_KEY = new Integer(1); + + protected ISharedObjectConfig config; + + protected Object data; + + protected String updaterID; + + protected IModelUpdater updater; + + public void init(ISharedObjectConfig config) throws SharedObjectInitException { + this.config = config; + Map props = config.getProperties(); + data = props.get(INITIAL_DATA_KEY); + updaterID = (String) props.get(MODEL_UPDATER_KEY); + if (updaterID == null) + throw new SharedObjectInitException("Model Updater is required."); + + IExtensionRegistry registry = Platform.getExtensionRegistry(); + if (registry == null) + throw new SharedObjectInitException("No Platform Extension Registry."); + + IConfigurationElement[] elements = registry.getConfigurationElementsFor("org.eclipse.ecf.example.pubsub.modelUpdater"); + for (int i = 0; i < elements.length; ++i) { + if (updaterID.equals(elements[i].getAttribute("id"))) { + try { + updater = (IModelUpdater) elements[i].createExecutableExtension("class"); + } catch (CoreException e) { + throw new SharedObjectInitException(e); + } catch (ClassCastException e) { + throw new SharedObjectInitException(e); + } + + break; + } + } + + if (updater == null) + throw new SharedObjectInitException("Could not find specified Model Updater."); + } + + public void handleEvent(Event event) { + if (event instanceof ISharedObjectActivatedEvent) { + ISharedObjectActivatedEvent e = (ISharedObjectActivatedEvent) event; + if (e.getActivatedID().equals(config.getSharedObjectID())) + activated(); + else + activated(e.getActivatedID()); + } else if (event instanceof ISharedObjectDeactivatedEvent) { + ISharedObjectDeactivatedEvent e = (ISharedObjectDeactivatedEvent) event; + if (e.getDeactivatedID().equals(config.getSharedObjectID())) + deactivated(); + else + deactivated(e.getDeactivatedID()); + } else if (event instanceof IContainerConnectedEvent) { + IContainerConnectedEvent e = (IContainerConnectedEvent) event; + if (e.getTargetID().equals(e.getLocalContainerID())) + connected(); + else + connected(e.getTargetID()); + } else if (event instanceof IContainerDisconnectedEvent) { + IContainerDisconnectedEvent e = (IContainerDisconnectedEvent) event; + if (e.getTargetID().equals(e.getLocalContainerID())) + disconnected(); + else + disconnected(e.getTargetID()); + } else if (event instanceof ISharedObjectMessageEvent) { + ISharedObjectMessageEvent e = (ISharedObjectMessageEvent) event; + received(e.getRemoteContainerID(), e.getData()); + } + } + + protected boolean isConnected() { + return config.getContext().getConnectedID() != null; + } + + protected void activated(ID sharedObjectID) { + } + + protected void activated() { + } + + protected void deactivated(ID sharedObjectID) { + } + + protected void deactivated() { + } + + protected void connected(ID containerID) { + } + + protected void connected() { + } + + protected void disconnected(ID containerID) { + } + + protected void disconnected() { + } + + protected void received(ID containerID, Object data) { + } + + protected void apply(Object data) { + updater.update(this.data, data); + } + + public void handleEvents(Event[] events) { + for (int i = 0; i < events.length; ++i) + handleEvent(events[i]); + } + + public ID getID() { + return config.getSharedObjectID(); + } + + public void dispose(ID containerID) { + config = null; + data = null; + updater = null; + } +} diff --git a/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/model/impl/LocalAgent.java b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/model/impl/LocalAgent.java new file mode 100644 index 000000000..252975c38 --- /dev/null +++ b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/model/impl/LocalAgent.java @@ -0,0 +1,65 @@ +/** + * Copyright (c) 2006 Ecliptical Software 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: + * Ecliptical Software Inc. - initial API and implementation + */ +package org.eclipse.ecf.pubsub.model.impl; + +import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.ecf.core.ISharedObjectContext; +import org.eclipse.ecf.core.ReplicaSharedObjectDescription; +import org.eclipse.ecf.core.identity.ID; +import org.eclipse.ecf.pubsub.model.IMasterModel; + +public class LocalAgent extends AgentBase implements IMasterModel { + + public synchronized void update(Object data) throws IOException { + apply(data); + config.getContext().sendMessage(null, data); + } + + public Map getProperties() { + return Collections.EMPTY_MAP; + } + + public void subscribe(ID containerID) { + ISharedObjectContext ctx = config.getContext(); + try { + ctx.sendCreate(containerID, createRemoteAgentDescription()); + } catch (IOException e) { + // TODO Log me! + e.printStackTrace(); + } + } + + public void unsubscribe(ID containerID) { + // TODO Auto-generated method stub + + } + + protected void deactivated() { + if (isConnected()) + try { + config.getContext().sendDispose(null); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + protected ReplicaSharedObjectDescription createRemoteAgentDescription() { + Map props = new HashMap(2); + props.put(INITIAL_DATA_KEY, data); + props.put(MODEL_UPDATER_KEY, updaterID); + return new ReplicaSharedObjectDescription(RemoteAgent.class, config.getSharedObjectID(), config.getHomeContainerID(), props); + } +} diff --git a/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/model/impl/RemoteAgent.java b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/model/impl/RemoteAgent.java new file mode 100644 index 000000000..076c42452 --- /dev/null +++ b/examples/bundles/org.eclipse.ecf.example.pubsub/src/org/eclipse/ecf/pubsub/model/impl/RemoteAgent.java @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2006 Ecliptical Software 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: + * Ecliptical Software Inc. - initial API and implementation + */ +package org.eclipse.ecf.pubsub.model.impl; + +import org.eclipse.ecf.core.identity.ID; +import org.eclipse.ecf.pubsub.model.IReplicaModel; + +public class RemoteAgent extends AgentBase implements IReplicaModel { + + public Object getData() { + return data; + } + + protected void disconnected() { + config.getContext().getSharedObjectManager().removeSharedObject(config.getSharedObjectID()); + } + + protected void disconnected(ID containerID) { + if (containerID.equals(config.getHomeContainerID())) + disconnected(); + } + + protected void received(ID containerID, Object data) { + apply(data); + } +} |
