package fr.jcgay.notification.notifier.growl;
import com.google.code.jgntp.Gntp;
import com.google.code.jgntp.GntpApplicationInfo;
import com.google.code.jgntp.GntpClient;
import com.google.code.jgntp.GntpNotification;
import com.google.code.jgntp.GntpNotificationInfo;
import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
import fr.jcgay.notification.Application;
import fr.jcgay.notification.DiscoverableNotifier;
import fr.jcgay.notification.Notification;
import fr.jcgay.notification.Notifier;
import org.slf4j.Logger;
import java.util.concurrent.TimeUnit;
import static com.google.code.jgntp.GntpNotification.Priority.HIGH;
import static com.google.code.jgntp.GntpNotification.Priority.HIGHEST;
import static com.google.code.jgntp.GntpNotification.Priority.NORMAL;
import static org.slf4j.LoggerFactory.getLogger;
public class GrowlNotifier implements DiscoverableNotifier {
private static final Logger LOGGER = getLogger(GrowlNotifier.class);
private final Application application;
private final GrowlConfiguration configuration;
private final GntpSlf4jListener logListener;
private GntpNotificationInfo gNotification;
private GntpClient gClient;
public GrowlNotifier(Application application, GrowlConfiguration configuration, GntpSlf4jListener logListener) {
LOGGER.debug("Configuring Growl for application {}: {}.", application, configuration);
this.application = application;
this.configuration = configuration;
this.logListener = logListener;
}
@Override
public Notifier init() {
if (isClientRegistered()) {
return this;
}
GntpApplicationInfo gApplication = Gntp.appInfo(application.name()).build();
gNotification = Gntp.notificationInfo(gApplication, application.id())
.icon(application.icon().toImage())
.build();
Gntp clientBuilder = Gntp.client(gApplication)
.onPort(configuration.port())
.forHost(configuration.host())
.withoutRetry()
.listener(logListener);
if (configuration.password() != null) {
clientBuilder.withPassword(configuration.password());
}
gClient = clientBuilder.build();
gClient.register();
try {
gClient.waitRegistration(1L, TimeUnit.SECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return this;
}
@Override
public void send(Notification notification) {
if (isClientRegistered()) {
GntpNotification success = Gntp.notification(gNotification, notification.title())
.text(notification.message())
.icon(notification.icon().toImage())
.priority(toPriority(notification.level()))
.build();
try {
gClient.notify(success, 5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
@Override
public void close() {
if (isClientRegistered()) {
try {
// Seems that the client can be shutdown without having processed all the notifications...
TimeUnit.SECONDS.sleep(1);
gClient.shutdown(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
@Override
public boolean isPersistent() {
return false;
}
@Override
public boolean tryInit() {
init();
boolean hasSucceeded = isClientRegistered();
if (!hasSucceeded) {
try {
gClient.shutdown(1, TimeUnit.SECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
return hasSucceeded;
}
private static GntpNotification.Priority toPriority(Notification.Level level) {
switch (level) {
case INFO:
return NORMAL;
case WARNING:
return HIGH;
case ERROR:
return HIGHEST;
default:
return NORMAL;
}
}
private boolean isClientRegistered() {
return gClient != null && gClient.isRegistered();
}
@Override
public int hashCode() {
return Objects.hashCode(application, configuration, logListener);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
final GrowlNotifier other = (GrowlNotifier) obj;
return Objects.equal(this.application, other.application)
&& Objects.equal(this.configuration, other.configuration)
&& Objects.equal(this.logListener, other.logListener);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("application", application)
.add("configuration", configuration)
.add("logListener", logListener)
.toString();
}
}