/* ********************************************************************** **
** Copyright notice **
** **
** (c) 2005-2009 RSSOwl Development Team **
** http://www.rssowl.org/ **
** **
** 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.rssowl.org/legal/epl-v10.html **
** **
** A copy is found in the file epl-v10.html and important notices to the **
** license from the team is found in the textfile LICENSE.txt distributed **
** in this package. **
** **
** This copyright notice MUST APPEAR in all copies of the file! **
** **
** Contributors: **
** RSSOwl Development Team - initial API and implementation **
** **
** ********************************************************************** */
package org.rssowl.core.internal.newsaction;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.osgi.util.NLS;
import org.rssowl.core.INewsAction;
import org.rssowl.core.Owl;
import org.rssowl.core.internal.Activator;
import org.rssowl.core.persist.IEntity;
import org.rssowl.core.persist.INews;
import org.rssowl.core.util.BatchedBuffer;
import org.rssowl.core.util.CoreUtils;
import org.rssowl.core.util.DateUtils;
import org.rssowl.core.util.StreamGobbler;
import org.rssowl.core.util.StringUtils;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
/**
* An implementation of {@link INewsAction} to show matching news in Growl. This
* is only supported on Mac.
*
* @author bpasero
*/
public class GrowlNotifyAction implements INewsAction {
/* Batch News-Events for every 5 seconds */
private static final int BATCH_INTERVAL = 5000;
/* Max number of items to show per Notification */
private static final int MAX_ITEMS_TO_SHOW = 5;
private static final String APPLICATION_NAME = "RSSOwl"; //$NON-NLS-1$
private static final String SEPARATOR = System.getProperty("line.separator"); //$NON-NLS-1$
private BatchedBuffer<INews> fBatchedBuffer;
private String fPathToGrowlNotify;
/** Initialize a Batched Buffer for Growl Notifications */
public GrowlNotifyAction() {
BatchedBuffer.Receiver<INews> receiver = new BatchedBuffer.Receiver<INews>() {
public IStatus receive(Collection<INews> items, Job job, IProgressMonitor monitor) {
try {
if (!Owl.isShuttingDown())
executeCommand(fPathToGrowlNotify, items);
}
/* Log any error message */
catch (IOException e) {
Activator.safeLogError(e.getMessage(), e);
}
return Status.OK_STATUS;
}
};
fBatchedBuffer = new BatchedBuffer<INews>(receiver, BATCH_INTERVAL);
}
/*
* @see org.rssowl.core.INewsAction#run(java.util.List, java.util.Map,
* java.lang.Object)
*/
public List<IEntity> run(List<INews> news, Map<INews, INews> replacements, Object data) {
/* Ensure to Pickup Replaces */
news = CoreUtils.replace(news, replacements);
/* Launch if file exists */
if (data instanceof String && new File((String) data).exists()) {
fPathToGrowlNotify = (String) data;
fBatchedBuffer.addAll(news);
}
/* Nothing to Save */
return Collections.emptyList();
}
private void executeCommand(String pathToGrowlnotify, Collection<INews> news) throws IOException {
if (StringUtils.isSet(pathToGrowlnotify)) {
List<String> commands = new ArrayList<String>();
commands.add(pathToGrowlnotify);
commands.add("--name"); //$NON-NLS-1$
commands.add(APPLICATION_NAME);
commands.add("-a"); //$NON-NLS-1$
commands.add(APPLICATION_NAME);
commands.add("-t"); //$NON-NLS-1$
commands.add(NLS.bind(Messages.GrowlNotifyAction_N_INCOMING_NEWS, news.size()));
commands.add("-m"); //$NON-NLS-1$
/* Sort News by Date */
Set<INews> sortedNews = new TreeSet<INews>(new Comparator<INews>() {
public int compare(INews news1, INews news2) {
Date date1 = DateUtils.getRecentDate(news1);
Date date2 = DateUtils.getRecentDate(news2);
int res = date2.compareTo(date1);
if (res != 0)
return res;
return -1;
}
});
sortedNews.addAll(news);
int i = 0;
StringBuilder message = new StringBuilder();
for (INews item : sortedNews) {
if (++i > MAX_ITEMS_TO_SHOW)
break;
message.append(CoreUtils.getHeadline(item, true)).append(SEPARATOR).append(SEPARATOR);
}
if (news.size() > MAX_ITEMS_TO_SHOW)
message.append(NLS.bind(Messages.GrowlNotifyAction_N_MORE, (news.size() - MAX_ITEMS_TO_SHOW)));
commands.add(message.toString());
/* Execute */
Process proc = Runtime.getRuntime().exec(commands.toArray(new String[commands.size()]));
/* Write Message to Growl */
OutputStream outputStream = proc.getOutputStream();
outputStream.write(message.toString().getBytes());
outputStream.close();
/* Let StreamGobbler handle error message */
StreamGobbler errorGobbler = new StreamGobbler(proc.getErrorStream());
/* Let StreamGobbler handle output */
StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream());
/* Flush both error and output streams */
errorGobbler.schedule();
outputGobbler.schedule();
}
}
/*
* @see org.rssowl.core.INewsAction#conflictsWith(org.rssowl.core.INewsAction)
*/
public boolean conflictsWith(INewsAction otherAction) {
return false;
}
/*
* @see org.rssowl.core.INewsAction#getLabel(java.lang.Object)
*/
public String getLabel(Object data) {
return null;
}
}