Package jetbrains.communicator.core.impl.dispatcher

Source Code of jetbrains.communicator.core.impl.dispatcher.AbstractMessageDispatcher$MessageProcessor

/*
* Copyright 2000-2006 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jetbrains.communicator.core.impl.dispatcher;

import com.thoughtworks.xstream.XStream;
import jetbrains.communicator.core.EventBroadcaster;
import jetbrains.communicator.core.EventVisitor;
import jetbrains.communicator.core.IDEtalkAdapter;
import jetbrains.communicator.core.IDEtalkEvent;
import jetbrains.communicator.core.dispatcher.Message;
import jetbrains.communicator.core.dispatcher.MessageDispatcher;
import jetbrains.communicator.core.impl.users.UserImpl;
import jetbrains.communicator.core.users.User;
import jetbrains.communicator.core.users.UserEvent;
import jetbrains.communicator.util.XMLUtil;
import org.apache.log4j.Logger;
import org.picocontainer.Disposable;

import java.io.File;
import java.util.*;

/**
* @author Kir
*/
public abstract class AbstractMessageDispatcher implements MessageDispatcher, Disposable {
  private static final Logger LOG = Logger.getLogger(AbstractMessageDispatcher.class);
  private XStream myXStream;

  private final File myDataDir;
  private final MyEventListener myEventListener;

  private final Object myUser2MessagesLock = new Object();
  private final Map<User,List<Message>> myUser2Messages = new HashMap<User, List<Message>>();
  private final EventBroadcaster myEventBroadcaster;
  private boolean myDispatching;

  protected AbstractMessageDispatcher(EventBroadcaster eventBroadcaster, File dataDir) {
    myDataDir = dataDir;
    myEventListener = new MyEventListener(eventBroadcaster);
    myEventBroadcaster = eventBroadcaster;
    load();
  }

  public void dispose() {
    myEventListener.dispose();
    //noinspection HardCodedStringLiteral
    LOG.debug("Disposed.");
  }

  protected abstract String getEventsFileName();

  protected boolean performDispatch(User user, Message message) {
    try {
      myDispatching = true;
      if (LOG.isDebugEnabled()) {
        //noinspection HardCodedStringLiteral
        LOG.debug("Start dispatching " + message + " to " + user);
      }
      boolean result = message.send(user);

      synchronized(myUser2MessagesLock) {
        List<Message> userMessages = getMessages(user);
        if (result) {
          userMessages.remove(message);
          if (userMessages.size() == 0) {
            myUser2Messages.remove(user);
          }
        }
        else if (!userMessages.contains(message) ){
          userMessages.add(message);
        }
      }

      if (LOG.isDebugEnabled()) {
        //noinspection HardCodedStringLiteral
        LOG.debug("End   dispatching " + message + " to " + user);
      }
      return result;
    } finally {
      myDispatching = false;
    }
  }

  public boolean hasUsersWithMessages() {
    synchronized(myUser2MessagesLock) {
      return !myUser2Messages.isEmpty();
    }
  }

  public User[] getUsersWithMessages() {
    synchronized(myUser2MessagesLock) {
      Set<User> users = myUser2Messages.keySet();
      return users.toArray(new User[users.size()]);
    }
  }

  public Message[] getPendingMessages(User user) {
    synchronized (myUser2MessagesLock) {
      List<Message> messages = myUser2Messages.get(user);
      if (messages == null) {
        return new Message[0];
      }

      return messages.toArray(new Message[messages.size()]);
    }
  }

  public EventBroadcaster getBroadcaster() {
    return myEventBroadcaster;
  }

  public boolean sendNow(User user, Message message) {
    boolean result = performDispatch(user, message);
    if (result) {
      save();
    }
    return result;
  }

  boolean isMessageDispatchInProgress() {
    return myDispatching;
  }

  protected void addPendingMessage(User user, Message message) {
    if (message == null) return;

    synchronized(myUser2MessagesLock) {
      List<Message> userMessages = getMessages(user);
      if (!userMessages.contains(message)) {
        if (LOG.isDebugEnabled()) {
          //noinspection HardCodedStringLiteral
          LOG.debug("Added pending message " + message + "\nfor user " + user);
        }
        userMessages.add(message);
        save();
      }
    }
  }

  protected void removePendingMessage(User user, int messageIndex) {
    synchronized(myUser2MessagesLock) {
      List<Message> userMessages = getMessages(user);
      userMessages.remove(messageIndex);
      save();
    }
  }

  protected void clearAll() {
    synchronized (myUser2MessagesLock) {
      myUser2Messages.clear();
      save();
    }
  }

  private List<Message> getMessages(User user) {
    synchronized (myUser2MessagesLock) {
      List<Message> result = myUser2Messages.get(user);
      if (result == null) {
        result = new ArrayList<Message>(5);
        myUser2Messages.put(user, result);
      }
      return result;
    }
  }

  protected final void load() {
    synchronized (myUser2MessagesLock) {
      Object pendingEventsStorable = XMLUtil.fromXml(getXStream(), getFileName(), false);
      if (pendingEventsStorable instanceof MessagesStorable) {
        loadFromStorableMessages((MessagesStorable) pendingEventsStorable);
      }
    }
  }

  protected void loadFromStorableMessages(MessagesStorable messagesStorable) {
    myUser2Messages.clear();
    myUser2Messages.putAll(messagesStorable.getUser2Messages());
  }

  private String getFileName() {
    return new File(myDataDir, getEventsFileName()).getAbsolutePath();
  }

  private void removeUser(User user) {
    synchronized (myUser2MessagesLock) {
      myUser2Messages.remove(user);
      save();
    }
  }

  @SuppressWarnings({"HardCodedStringLiteral"})
  protected void save() {
    if (myDataDir == null || !myDataDir.exists()) return;

    LOG.debug("Save start");
    synchronized(myUser2MessagesLock) {
      XMLUtil.toXml(getXStream(), getFileName(), createStorableMessages());
    }
    LOG.debug("Save finish");
  }

  protected MessagesStorable createStorableMessages() {
    return new MessagesStorable(myUser2Messages);
  }

  @SuppressWarnings({"HardCodedStringLiteral"})
  private XStream getXStream() {
    if (myXStream == null) {
      myXStream = XMLUtil.createXStream();
      myXStream.alias("user", UserImpl.class);
      myXStream.alias("pendingEvents", MessagesStorable.class);
    }

    return myXStream;
  }

  private class MyEventListener extends IDEtalkAdapter {
    private final EventBroadcaster myBroadcaster;

    MyEventListener(EventBroadcaster broadcaster) {
      myBroadcaster = broadcaster;
      broadcaster.addListener(this);
    }

    public void dispose() {
      myBroadcaster.removeListener(this);
    }

    public void afterChange(IDEtalkEvent event) {
      event.accept(new EventVisitor(){
        @SuppressWarnings({"RefusedBequest"})
        @Override public void visitUserRemoved(UserEvent.Removed event) {
          removeUser(event.getUser());
        }
      });
    }
  }

  protected interface MessageProcessor {

    /** returns true if processing should be stopped */
    boolean process(User user, Message message);
  }

}
TOP

Related Classes of jetbrains.communicator.core.impl.dispatcher.AbstractMessageDispatcher$MessageProcessor

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.