/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package com.liferay.push.notifications.sender.android.internal;
import com.google.android.gcm.server.Constants;
import com.google.android.gcm.server.Message;
import com.google.android.gcm.server.Message.Builder;
import com.google.android.gcm.server.MulticastResult;
import com.google.android.gcm.server.Result;
import com.google.android.gcm.server.Sender;
import com.liferay.portal.configuration.metatype.bnd.util.ConfigurableUtil;
import com.liferay.portal.kernel.json.JSONObject;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.messaging.MessageBusUtil;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.push.notifications.constants.PushNotificationsConstants;
import com.liferay.push.notifications.constants.PushNotificationsDestinationNames;
import com.liferay.push.notifications.exception.PushNotificationsException;
import com.liferay.push.notifications.sender.PushNotificationsSender;
import com.liferay.push.notifications.sender.Response;
import com.liferay.push.notifications.sender.android.internal.configuration.AndroidPushNotificationsSenderConfiguration;
import com.liferay.push.notifications.service.PushNotificationsDeviceLocalService;
import java.util.List;
import java.util.Map;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Modified;
import org.osgi.service.component.annotations.Reference;
/**
* @author Silvio Santos
* @author Bruno Farache
*/
@Component(
configurationPid = "com.liferay.push.notifications.sender.android.internal.configuration.AndroidPushNotificationsSenderConfiguration",
immediate = true,
property = {"platform=" + AndroidPushNotificationsSender.PLATFORM}
)
public class AndroidPushNotificationsSender implements PushNotificationsSender {
public static final String PLATFORM = "android";
@Override
public void send(List<String> tokens, JSONObject payloadJSONObject)
throws Exception {
if (_sender == null) {
throw new PushNotificationsException(
"Android push notifications sender is not configured properly");
}
Message message = buildMessage(payloadJSONObject);
MulticastResult multicastResult = _sender.send(
message, tokens,
_androidPushNotificationsSenderConfiguration.retries());
validateMulticastResult(tokens, payloadJSONObject, multicastResult);
}
@Activate
@Modified
protected void activate(Map<String, Object> properties) {
_androidPushNotificationsSenderConfiguration =
ConfigurableUtil.createConfigurable(
AndroidPushNotificationsSenderConfiguration.class, properties);
String apiKey = _androidPushNotificationsSenderConfiguration.apiKey();
if (Validator.isNull(apiKey)) {
_sender = null;
return;
}
_sender = new Sender(apiKey);
}
protected Message buildMessage(JSONObject payloadJSONObject) {
Builder builder = new Builder();
builder.addData(
PushNotificationsConstants.KEY_PAYLOAD,
payloadJSONObject.toString());
return builder.build();
}
@Deactivate
protected void deactivate() {
_sender = null;
}
@Reference(unbind = "-")
protected void setPushNotificationsDeviceLocalService(
PushNotificationsDeviceLocalService
pushNotificationsDeviceLocalService) {
_pushNotificationsDeviceLocalService =
pushNotificationsDeviceLocalService;
}
protected void validateMulticastResult(
List<String> tokens, JSONObject payloadJSONObject,
MulticastResult multicastResult) {
List<Result> results = multicastResult.getResults();
for (int i = 0; i < results.size(); i++) {
Result result = results.get(i);
String token = tokens.get(i);
Response response = new AndroidResponse(
result, token, payloadJSONObject);
MessageBusUtil.sendMessage(
PushNotificationsDestinationNames.PUSH_NOTIFICATION_RESPONSE,
response);
if ((multicastResult.getCanonicalIds() == 0) &&
(multicastResult.getFailure() == 0)) {
continue;
}
String canonicalRegistrationId =
result.getCanonicalRegistrationId();
String messageId = result.getMessageId();
if (Validator.isNotNull(canonicalRegistrationId) &&
Validator.isNotNull(messageId)) {
try {
_pushNotificationsDeviceLocalService.updateToken(
token, canonicalRegistrationId);
}
catch (Exception e) {
if (_log.isWarnEnabled()) {
_log.warn("Unable to update token " + token);
}
}
}
String errorCodeName = result.getErrorCodeName();
if (Validator.isNotNull(errorCodeName)) {
if (errorCodeName.equals(
Constants.ERROR_INVALID_REGISTRATION) ||
errorCodeName.equals(Constants.ERROR_MISMATCH_SENDER_ID) ||
errorCodeName.equals(Constants.ERROR_NOT_REGISTERED)) {
try {
_pushNotificationsDeviceLocalService.
deletePushNotificationsDevice(token);
}
catch (Exception e) {
if (_log.isWarnEnabled()) {
_log.warn(
"Unable to delete invalid token " + token);
}
}
}
}
}
}
private static final Log _log = LogFactoryUtil.getLog(
AndroidPushNotificationsSender.class);
private volatile AndroidPushNotificationsSenderConfiguration
_androidPushNotificationsSenderConfiguration;
private PushNotificationsDeviceLocalService
_pushNotificationsDeviceLocalService;
private volatile Sender _sender;
}