Package org.eclipse.ecf.internal.sync.resources.core

Source Code of org.eclipse.ecf.internal.sync.resources.core.ResourcesShare

/*******************************************************************************
* Copyright (c) 2009 Remy Chi Jian Suen 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:
*    Remy Chi Jian Suen <remy.suen@gmail.com> - initial API and implementation
******************************************************************************/
package org.eclipse.ecf.internal.sync.resources.core;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.MultiRule;
import org.eclipse.ecf.core.identity.ID;
import org.eclipse.ecf.core.util.ECFException;
import org.eclipse.ecf.datashare.AbstractShare;
import org.eclipse.ecf.datashare.IChannelContainerAdapter;
import org.eclipse.ecf.sync.IModelChange;
import org.eclipse.ecf.sync.IModelChangeMessage;

public class ResourcesShare extends AbstractShare {

  private Boolean response;

  private Set sharedProjects = new HashSet();

  private ID receiverID;

  private ID containerID;

  private ID localID;

  public ResourcesShare(ID containerID, IChannelContainerAdapter adapter)
      throws ECFException {
    super(adapter);
    this.containerID = containerID;
  }

  private void attachListener() {
    if (sharedProjects.size() == 1) {
      SyncResourcesCore.getDefault().attachListener();
    }
  }

  private void detachListener() {
    if (sharedProjects.isEmpty()) {
      SyncResourcesCore.getDefault().detachListener();
    }
  }

  public void sendResponse(boolean accept, String projectName) {
    try {
      if (accept) {
        send(receiverID, new AcceptMessage(projectName));
      } else {
        send(receiverID, new DenyMessage(projectName));
      }
    } catch (ECFException e) {
      // TODO handle this
      e.printStackTrace();
    }
  }

  public Boolean getResponse() {
    if (response == null) {
      return null;
    }
    Boolean temp = response;
    response = null;
    return temp;
  }

  public ID getContainerID() {
    return containerID;
  }

  public ID getReceiverID() {
    return receiverID;
  }

  public ID getLocalID() {
    return localID;
  }

  public boolean isSharing(String projectName) {
    synchronized (sharedProjects) {
      return sharedProjects.contains(projectName);
    }
  }

  public void startShare(ID fromId, ID toID, String projectName)
      throws ECFException {
    if (sharedProjects.add(projectName)) {
      // reset in case we have a stale one
      response = null;
     
      try {
        send(toID, new StartMessage(projectName, fromId, toID));
        localID = fromId;
        receiverID = toID;
        attachListener();
      } catch (ECFException e) {
        receiverID = null;
        sharedProjects.remove(projectName);
        detachListener();
        throw e;
      }
    }
  }

  public void stopSharing(String projectName) {
    if (sharedProjects.remove(projectName)) {
      try {
        send(receiverID, new StopMessage(projectName));
      } catch (ECFException e) {
        // TODO handle this
        e.printStackTrace();
      } finally {
        receiverID = null;
      }

      detachListener();
    }
  }

  private void send(ID toID, Message message) throws ECFException {
    sendMessage(toID, message.serialize());
  }

  void send(byte[] bytes) throws ECFException {
    sendMessage(receiverID, bytes);
  }

  void sendResourceChangeMessage(IResource resource, int kind) {
    try {
      IModelChange change = ResourceChangeMessage.createResourceChange(
          resource, kind);
      IModelChangeMessage[] messages = ResourcesSynchronizationStrategy
          .getInstance().registerLocalChange(change);
      for (int i = 0; i < messages.length; i++) {
        send(messages[i].serialize());
      }
    } catch (ECFException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }

  protected void handleStartMessage(StartMessage msg) {
    receiverID = msg.getFromId();
    localID = msg.getLocalId();
    sharedProjects.add(msg.getProjectName());
    attachListener();
  }

  private void handleStopMessage(StopMessage msg) {
    sharedProjects.remove(msg.getProjectName());
    detachListener();
  }

  private void handleResourceChangeMessage(byte[] data) throws Exception {
    IModelChange remoteChange = ResourcesSynchronizationStrategy
        .getInstance().deserializeRemoteChange(data);
    final IModelChange[] remoteChanges = ResourcesSynchronizationStrategy
        .getInstance().transformRemoteChange(remoteChange);

    // create a scheduling rule to lock the projects
    ISchedulingRule[] rules = new ISchedulingRule[sharedProjects.size()];
    int index = 0;
    for (Iterator it = sharedProjects.iterator(); it.hasNext();) {
      String projectName = (String) it.next();

      rules[index] = ResourcesPlugin.getWorkspace().getRoot().getProject(
          projectName);
      index++;
    }

    try {
      // lock to prevent resource changes from being propagated
      lock(remoteChanges);
      applyRemoteChanges(remoteChanges, new MultiRule(rules));
    } finally {
      // unlock now that we've applied the remote changes to our
      // own workspace
      unlock(remoteChanges);
    }

    if (remoteChange instanceof BatchModelChange) {
      BatchModelChange batchChange = (BatchModelChange) remoteChange;
      batchChange.setOutgoing(false);
      batchChange.setTime(System.currentTimeMillis());

      SyncResourcesCore.add(batchChange);
    }
  }

  protected void lock(IModelChange[] remoteChanges) {
    SyncResourcesCore.lock();
  }

  protected void unlock(IModelChange[] remoteChanges) {
    SyncResourcesCore.unlock();
  }

  private void applyRemoteChanges(final IModelChange[] remoteChanges,
      ISchedulingRule rule) throws CoreException {
    ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
      public void run(IProgressMonitor monitor) throws CoreException {
        monitor.beginTask("Processing remote changes...",
            remoteChanges.length);
        for (int i = 0; i < remoteChanges.length; i++) {
          if (monitor.isCanceled()) {
            return;
          }
          // applies the resource changes
          remoteChanges[i].applyToModel(containerID);
          monitor.worked(1);
        }
        monitor.done();
      }
    }, rule, IWorkspace.AVOID_UPDATE, null);

  }

  protected void handleMessage(ID fromContainerID, byte[] data) {
    try {
      Object message = Message.deserialize(data);
      if (message instanceof StartMessage) {
        handleStartMessage((StartMessage) message);
      } else if (message instanceof StopMessage) {
        handleStopMessage((StopMessage) message);
      } else if (message instanceof AcceptMessage) {
        response = Boolean.TRUE;
      } else if (message instanceof DenyMessage) {
        sharedProjects.remove(((DenyMessage) message).getProjectName());
        receiverID = null;
        detachListener();
        response = Boolean.FALSE;
      } else {
        handleResourceChangeMessage(data);
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}
TOP

Related Classes of org.eclipse.ecf.internal.sync.resources.core.ResourcesShare

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.