/** * 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.identity.ID; import org.eclipse.ecf.core.sharedobject.ISharedObject; import org.eclipse.ecf.core.sharedobject.ISharedObjectConfig; import org.eclipse.ecf.core.sharedobject.ISharedObjectContext; import org.eclipse.ecf.core.sharedobject.ISharedObjectManager; import org.eclipse.ecf.core.sharedobject.ReplicaSharedObjectDescription; import org.eclipse.ecf.core.sharedobject.SharedObjectInitException; import org.eclipse.ecf.core.sharedobject.events.ISharedObjectActivatedEvent; import org.eclipse.ecf.core.sharedobject.events.ISharedObjectCreateResponseEvent; import org.eclipse.ecf.core.sharedobject.events.ISharedObjectDeactivatedEvent; import org.eclipse.ecf.core.util.Event; import org.eclipse.ecf.pubsub.IPublishedService; import org.eclipse.ecf.pubsub.ISubscribedService; import org.eclipse.ecf.pubsub.ISubscriber; import org.eclipse.ecf.pubsub.ISubscription; import org.eclipse.ecf.pubsub.ISubscriptionCallback; public class SubscriptionAgent extends PlatformObject implements ISharedObject, ISubscriber { 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 ISubscribedService svc; protected boolean disposed; public synchronized void subscribed(ISubscribedService svc) { if (disposed) throw new IllegalStateException("Already disposed."); this.svc = svc; callback.subscribed(new Subscription()); } public void init(ISharedObjectConfig config) throws SharedObjectInitException { Map props = config.getProperties(); if (config.getContext().getLocalContainerID().equals(config.getHomeContainerID())) { 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"); this.config = config; } public void handleEvent(Event event) { if (event instanceof ISharedObjectActivatedEvent) { ISharedObjectActivatedEvent e = (ISharedObjectActivatedEvent) event; if (e.getActivatedID().equals(config.getSharedObjectID())) activated(); } else if (event instanceof ISharedObjectDeactivatedEvent) { ISharedObjectDeactivatedEvent e = (ISharedObjectDeactivatedEvent) event; if (e.getDeactivatedID().equals(config.getSharedObjectID())) deactivated(); } 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()); } catch (IOException e) { callback.requestFailed(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, config.getSharedObjectID()); } else { ctx.sendCreateResponse(homeContainerID, new IllegalArgumentException("Not an IPublishedService."), -1); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { ctx.getSharedObjectManager().removeSharedObject(config.getSharedObjectID()); } } protected void deactivated() { if (isPrimary()) { synchronized (this) { disposed = true; if (svc != null) svc.unsubscribe(config.getSharedObjectID()); } } } protected void received(ISharedObjectCreateResponseEvent e) { if (e.getRemoteContainerID().equals(containerID) && e.getSenderSharedObjectID().equals(config.getSharedObjectID())) { callback.requestFailed(e.getException()); config.getContext().getSharedObjectManager().removeSharedObject(config.getSharedObjectID()); } } 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; callback = null; svc = null; } protected class Subscription implements ISubscription { public ID getID() { return sharedObjectID; } public ID getHomeContainerID() { return containerID; } public ISubscribedService getSubscribedService() { return svc; } public void dispose() { synchronized (SubscriptionAgent.this) { if (!disposed) config.getContext().getSharedObjectManager().removeSharedObject(config.getSharedObjectID()); } } } }