/**
* Copyright 2010 JBoss Inc
*
* 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 org.drools.guvnor.server.repository;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import org.drools.guvnor.server.util.LoggingHelper;
import org.drools.repository.AssetItem;
import org.drools.repository.RulesRepository;
import org.drools.repository.UserInfo;
import org.drools.repository.UserInfo.InboxEntry;
/**
* This service the "delivery" of messages to users inboxes for events.
* Ideally only one instance of this running at a time (at least on a node) to avoid doubling up.
*
* @author Michael Neale
*/
public class MailboxService {
private static final LoggingHelper log = LoggingHelper.getLogger( MailboxService.class );
public static final String MAILMAN = "mailman";
private static ExecutorService executor = null;
private static MailboxService INSTANCE = null;
/**
* Should be the for the "mailman" user.
*/
private RulesRepository repository;
public static MailboxService getInstance() {
if (INSTANCE==null) {
INSTANCE = new MailboxService();
executor = Executors.newSingleThreadExecutor();
}
return INSTANCE;
}
private MailboxService() {}
public void init(RulesRepository systemRepo) {
log.info("Starting mailbox service");
this.repository = systemRepo;
log.info("mailbox service is up");
}
public void stop() {
log.info("Shutting down mailbox service");
executor.shutdown();
try {
System.out.println("IS DOWN: " + executor.isTerminated());
if (!executor.awaitTermination(10, TimeUnit.SECONDS)) {
executor.shutdownNow();
System.out.println("IS DOWN2: " + executor.isTerminated());
if (!executor.awaitTermination(10, TimeUnit.SECONDS)) {
System.err.println("executor did not terminate");
}
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
executor.shutdownNow();
Thread.currentThread().interrupt();
}
INSTANCE=null;
log.info("Mailbox service is shutdown.");
}
public void wakeUp() {
log.debug("Waking up");
executor.execute(new Runnable() {
public void run() {
processOutgoing();
}
});
}
/** Process any waiting messages */
void processOutgoing() {
//log.info("Processing outgoing messages");
if (repository != null) {
UserInbox mailman = new UserInbox(repository, MAILMAN);
final List<UserInfo.InboxEntry> es = mailman.loadIncoming();
log.debug("Outgoing messages size " + es.size());
//wipe out inbox for mailman here...
UserInfo.eachUser(this.repository, new UserInfo.Command() {
public void process(final String toUser) {
//String toUser = userNode.getName();
log.debug("Processing any inbound messages for " + toUser);
if (toUser.equals(MAILMAN)) return;
UserInbox inbox = new UserInbox(repository, toUser);
Set<String> recentEdited = makeSetOf(inbox.loadRecentEdited());
for (UserInfo.InboxEntry e : es) {
//the user who edited the item wont receive a message in inbox.
if (!e.from.equals(toUser) && recentEdited.contains(e.assetUUID)) {
inbox.addToIncoming(e.assetUUID, e.note, e.from);
}
}
}
});
mailman.clearIncoming();
repository.save();
}
}
private Set<String> makeSetOf(List<InboxEntry> inboxEntries) {
Set<String> entries = new HashSet<String>();
for(InboxEntry e : inboxEntries) {
entries.add(e.assetUUID);
}
return entries;
}
/**
* Call this to note that there has been a change - will then publish to any interested parties.
* @param item
*/
public void recordItemUpdated(AssetItem item) {
final String id = item.getUUID();
final String name = item.getName();
final String from = item.getRulesRepository().getSession().getUserID();
executor.execute(new Runnable() {
public void run() {
if (repository!=null) {
// write the message to the admins outbox
UserInbox inbox = new UserInbox(repository, MAILMAN);
inbox.addToIncoming(id, name, from);
processOutgoing();
repository.save();
}
}
});
}
}