/* * Copyright (c) 2014. * * BaasBox - info-at-baasbox.com * * 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 com.baasbox.service.push; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import org.apache.commons.lang3.StringUtils; import com.baasbox.BBConfiguration; import com.baasbox.configuration.Push; import com.baasbox.dao.UserDao; import com.baasbox.exception.BaasBoxPushException; import com.baasbox.exception.UserNotFoundException; import com.baasbox.service.logging.BaasBoxLogger; import com.baasbox.service.logging.PushLogger; import com.baasbox.service.push.providers.Factory; import com.baasbox.service.push.providers.Factory.ConfigurationKeys; import com.baasbox.service.push.providers.Factory.VendorOS; import com.baasbox.service.push.providers.IPushServer; import com.fasterxml.jackson.databind.JsonNode; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; import com.orientechnologies.orient.core.record.impl.ODocument; public class PushService { private ImmutableMap<ConfigurationKeys, String> getPushParameters(Integer pushProfile){ PushLogger.getInstance().addMessage(".... profile: %d " , pushProfile); ImmutableMap<Factory.ConfigurationKeys,String> response=null; if(pushProfile==2){ if (Push.PROFILE2_PUSH_SANDBOX_ENABLE.getValueAsBoolean()) { if (BaasBoxLogger.isDebugEnabled()) BaasBoxLogger.debug("Push profile choosen for sandbox environment: 2"); response = ImmutableMap.of( ConfigurationKeys.ANDROID_API_KEY, ""+Push.PROFILE2_SANDBOX_ANDROID_API_KEY.getValueAsString(), ConfigurationKeys.APPLE_TIMEOUT, ""+Push.PROFILE2_PUSH_APPLE_TIMEOUT.getValueAsString(), ConfigurationKeys.IOS_CERTIFICATE, ""+Push.PROFILE2_SANDBOX_IOS_CERTIFICATE.getValueAsString(), ConfigurationKeys.IOS_CERTIFICATE_PASSWORD, ""+Push.PROFILE2_SANDBOX_IOS_CERTIFICATE_PASSWORD.getValueAsString(), ConfigurationKeys.IOS_SANDBOX,""+Boolean.TRUE.toString() ); }else{ if (BaasBoxLogger.isDebugEnabled()) BaasBoxLogger.debug("Push profile choosen for production environment: 2"); response = ImmutableMap.of( ConfigurationKeys.ANDROID_API_KEY, ""+Push.PROFILE2_PRODUCTION_ANDROID_API_KEY.getValueAsString(), ConfigurationKeys.APPLE_TIMEOUT, ""+Push.PROFILE2_PUSH_APPLE_TIMEOUT.getValueAsString(), ConfigurationKeys.IOS_CERTIFICATE,""+ Push.PROFILE2_PRODUCTION_IOS_CERTIFICATE.getValueAsString(), ConfigurationKeys.IOS_CERTIFICATE_PASSWORD, ""+Push.PROFILE2_PRODUCTION_IOS_CERTIFICATE_PASSWORD.getValueAsString(), ConfigurationKeys.IOS_SANDBOX,""+Boolean.FALSE.toString() ); } } else if(pushProfile==3){ if (Push.PROFILE3_PUSH_SANDBOX_ENABLE.getValueAsBoolean()) { if (BaasBoxLogger.isDebugEnabled()) BaasBoxLogger.debug("Push profile choosen for sandbox environment: 3"); response = ImmutableMap.of( ConfigurationKeys.ANDROID_API_KEY, ""+Push.PROFILE3_SANDBOX_ANDROID_API_KEY.getValueAsString(), ConfigurationKeys.APPLE_TIMEOUT, ""+Push.PROFILE3_PUSH_APPLE_TIMEOUT.getValueAsString(), ConfigurationKeys.IOS_CERTIFICATE, ""+Push.PROFILE3_SANDBOX_IOS_CERTIFICATE.getValueAsString(), ConfigurationKeys.IOS_CERTIFICATE_PASSWORD, ""+Push.PROFILE3_SANDBOX_IOS_CERTIFICATE_PASSWORD.getValueAsString(), ConfigurationKeys.IOS_SANDBOX,""+Boolean.TRUE.toString() ); }else{ if (BaasBoxLogger.isDebugEnabled()) BaasBoxLogger.debug("Push profile choosen for production environment: 3"); response = ImmutableMap.of( ConfigurationKeys.ANDROID_API_KEY, ""+Push.PROFILE3_PRODUCTION_ANDROID_API_KEY.getValueAsString(), ConfigurationKeys.APPLE_TIMEOUT, ""+Push.PROFILE3_PUSH_APPLE_TIMEOUT.getValueAsString(), ConfigurationKeys.IOS_CERTIFICATE,""+ Push.PROFILE3_PRODUCTION_IOS_CERTIFICATE.getValueAsString(), ConfigurationKeys.IOS_CERTIFICATE_PASSWORD, ""+Push.PROFILE3_PRODUCTION_IOS_CERTIFICATE_PASSWORD.getValueAsString(), ConfigurationKeys.IOS_SANDBOX,""+Boolean.FALSE.toString() ); } } else if (Push.PROFILE1_PUSH_SANDBOX_ENABLE.getValueAsBoolean()){ if (BaasBoxLogger.isDebugEnabled()) BaasBoxLogger.debug("Push profile choosen for sandbox environment: 1(default)"); response = ImmutableMap.of( ConfigurationKeys.ANDROID_API_KEY, ""+Push.PROFILE1_SANDBOX_ANDROID_API_KEY.getValueAsString(), ConfigurationKeys.APPLE_TIMEOUT, ""+Push.PROFILE1_PUSH_APPLE_TIMEOUT.getValueAsString(), ConfigurationKeys.IOS_CERTIFICATE, ""+Push.PROFILE1_SANDBOX_IOS_CERTIFICATE.getValueAsString(), ConfigurationKeys.IOS_CERTIFICATE_PASSWORD, ""+Push.PROFILE1_SANDBOX_IOS_CERTIFICATE_PASSWORD.getValueAsString(), ConfigurationKeys.IOS_SANDBOX,""+Boolean.TRUE.toString() ); }else{ if (BaasBoxLogger.isDebugEnabled()) BaasBoxLogger.debug("Push profile choosen for production environment: 1(default)"); response = ImmutableMap.of( ConfigurationKeys.ANDROID_API_KEY, ""+Push.PROFILE1_PRODUCTION_ANDROID_API_KEY.getValueAsString(), ConfigurationKeys.APPLE_TIMEOUT, ""+Push.PROFILE1_PUSH_APPLE_TIMEOUT.getValueAsString(), ConfigurationKeys.IOS_CERTIFICATE,""+ Push.PROFILE1_PRODUCTION_IOS_CERTIFICATE.getValueAsString(), ConfigurationKeys.IOS_CERTIFICATE_PASSWORD, ""+Push.PROFILE1_PRODUCTION_IOS_CERTIFICATE_PASSWORD.getValueAsString(), ConfigurationKeys.IOS_SANDBOX,""+Boolean.FALSE.toString() ); } HashMap toLog = new HashMap(response); toLog.put(ConfigurationKeys.ANDROID_API_KEY,"<hidden>"); toLog.put(ConfigurationKeys.IOS_CERTIFICATE,"<hidden>"); PushLogger.getInstance().addMessage("...... configuration: %s " , toLog); return response; } public boolean[] send(String message, List<String> usernames, List<Integer> pushProfiles, JsonNode bodyJson, boolean[] withError) throws Exception{ PushLogger pushLogger = PushLogger.getInstance(); List<String> iosToken = new ArrayList<String>(); List<String> androidToken = new ArrayList<String>(); com.baasbox.db.DbHelper.reconnectAsAdmin(); for(String username : usernames) { pushLogger.addMessage("Processing user %s ...",username ); if (BaasBoxLogger.isDebugEnabled()) BaasBoxLogger.debug("Try to send a message (" + message + ") to " + username); UserDao udao = UserDao.getInstance(); ODocument user = udao.getByUserName(username); if (user==null) { pushLogger.addMessage("+++ ERROR: User %s does not exist!",username); if (BaasBoxLogger.isDebugEnabled()) BaasBoxLogger.debug("User " + username + " does not exist"); throw new UserNotFoundException("User " + username + " does not exist"); } ODocument userSystemProperties=user.field(UserDao.ATTRIBUTES_SYSTEM); if (BaasBoxLogger.isDebugEnabled()) BaasBoxLogger.debug("userSystemProperties: " + userSystemProperties); pushLogger.addMessage("... system properties %s ...", userSystemProperties ); List<ODocument> loginInfos=userSystemProperties.field(UserDao.USER_LOGIN_INFO); if (BaasBoxLogger.isDebugEnabled()) BaasBoxLogger.debug("Sending to " + loginInfos.size() + " devices"); pushLogger.addMessage("... the message will be sent to %d device(s)...",loginInfos.size()); pushLogger.addMessage("... retrieving device(s) info..."); for(ODocument loginInfo : loginInfos){ pushLogger.addMessage("...... login info: %s ...", loginInfo); String pushToken=loginInfo.field(UserDao.USER_PUSH_TOKEN); String vendor=loginInfo.field(UserDao.USER_DEVICE_OS); pushLogger.addMessage("......... device token: %s ...", pushToken); pushLogger.addMessage("......... os/vendor: %s ...", vendor); if (BaasBoxLogger.isDebugEnabled()) BaasBoxLogger.debug ("push token: " + pushToken); if (BaasBoxLogger.isDebugEnabled()) BaasBoxLogger.debug ("vendor: " + vendor); if(!StringUtils.isEmpty(vendor) && !StringUtils.isEmpty(pushToken)){ VendorOS vos = VendorOS.getVendorOs(vendor); if (BaasBoxLogger.isDebugEnabled()) BaasBoxLogger.debug("vos: " + vos); if (vos!=null){ switch(vos) { case IOS: iosToken.add(pushToken); break; case ANDROID: androidToken.add(pushToken); break; } } //vos!=null }//(!StringUtils.isEmpty(vendor) && !StringUtils.isEmpty(deviceId) }//for (ODocument loginInfo : loginInfos) }//for (String username : usernames) int i=0; pushLogger.addMessage("... retrieving app(s) push configurations and sending notifications..."); for(Integer pushProfile : pushProfiles) { pushLogger.addMessage("...... profile %d ...",pushProfile); HashMap<Factory.VendorOS,IPushServer> allVendors= Factory.getAllIstances(); ImmutableMap<ConfigurationKeys, String> pushParam = getPushParameters(pushProfile); IPushServer apnServer = allVendors.get(VendorOS.IOS); apnServer.setConfiguration(pushParam); IPushServer gcmServer = allVendors.get(VendorOS.ANDROID); gcmServer.setConfiguration(pushParam); pushLogger.addMessage("......... sending to %d iOS device(s)...",iosToken.size()); if(iosToken.size()>0) { for(List<String> thousandUsersApple : Lists.partition(iosToken, 1)){ withError[i]=apnServer.send(message, thousandUsersApple, bodyJson); if (withError[i]) pushLogger.addMessage("........... WARNING: something went wrong sending this batch (%d) of messages to iOS devices",i); } i++; } pushLogger.addMessage("......... sending to %d Android device(s)...",androidToken.size()); if(androidToken.size()>0) { for(List<String> thousandUsersAndroid: Lists.partition(androidToken,1000)){ //needed for the GCM sending limit withError[i]=gcmServer.send(message, thousandUsersAndroid, bodyJson); if (withError[i]) pushLogger.addMessage("........... WARNING: something went wrong sending this batch (%d) of messages to Android devices",i); } i++; } } com.baasbox.db.DbHelper.reconnectAsAuthenticatedUser(); return withError; }//send public boolean validate(List<Integer> pushProfiles) throws IOException, BaasBoxPushException { for(Integer pushProfile : pushProfiles) { if((pushProfile!=1) && (pushProfile!=2) && (pushProfile!=3)) { PushLogger pushLogger = PushLogger.getInstance(); pushLogger.addMessage("+++ ERROR: Error with profiles (accepted values are: 1,2 or 3). Got %d", pushProfile); throw new PushProfileInvalidException("Error with profiles (accepted values are:1,2 or 3)"); } if (!isMocked()){ if((pushProfile==1) && (!Push.PROFILE1_PUSH_PROFILE_ENABLE.getValueAsBoolean())) throw new PushProfileDisabledException("Profile not enabled"); if((pushProfile==2) && (!Push.PROFILE2_PUSH_PROFILE_ENABLE.getValueAsBoolean())) throw new PushProfileDisabledException("Profile not enabled"); if((pushProfile==3) && (!Push.PROFILE3_PUSH_PROFILE_ENABLE.getValueAsBoolean())) throw new PushProfileDisabledException("Profile not enabled"); }//isMocked } return true; } public boolean isMocked(){ if (BBConfiguration.getPushMock()) BaasBoxLogger.warn("PushService is Mocked!!"); return BBConfiguration.getPushMock(); } /*public void sendAll(String message) throws PushNotInitializedException, UserNotFoundException, SqlInjectionException{ }*/ }