commit 491d43074107c3ce71186e3895c4ab69afa5e20a Author: 谢洪龙 <599179587@qq.com> Date: Wed Aug 23 12:20:15 2017 +0800 初始化 diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..d2e63ba --- /dev/null +++ b/.classpath @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.project b/.project new file mode 100644 index 0000000..b604f13 --- /dev/null +++ b/.project @@ -0,0 +1,42 @@ + + + quartzPro + + + + + + org.eclipse.wst.jsdt.core.javascriptValidator + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.wst.common.project.facet.core.builder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + org.eclipse.wst.validation.validationbuilder + + + + + + org.eclipse.jem.workbench.JavaEMFNature + org.eclipse.wst.common.modulecore.ModuleCoreNature + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + org.eclipse.wst.common.project.facet.core.nature + org.eclipse.wst.jsdt.core.jsNature + + diff --git a/.settings/.jsdtscope b/.settings/.jsdtscope new file mode 100644 index 0000000..b72a6a4 --- /dev/null +++ b/.settings/.jsdtscope @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..980ebe9 --- /dev/null +++ b/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,3 @@ +eclipse.preferences.version=1 +encoding//src/main/resources/jPpush.properties=UTF-8 +encoding/=UTF-8 diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..6b5aebc --- /dev/null +++ b/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,13 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.7 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.source=1.7 diff --git a/.settings/org.eclipse.m2e.core.prefs b/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 0000000..f897a7f --- /dev/null +++ b/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component new file mode 100644 index 0000000..97577c0 --- /dev/null +++ b/.settings/org.eclipse.wst.common.component @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/.settings/org.eclipse.wst.common.project.facet.core.xml b/.settings/org.eclipse.wst.common.project.facet.core.xml new file mode 100644 index 0000000..50e7352 --- /dev/null +++ b/.settings/org.eclipse.wst.common.project.facet.core.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/.settings/org.eclipse.wst.jsdt.ui.superType.container b/.settings/org.eclipse.wst.jsdt.ui.superType.container new file mode 100644 index 0000000..3bd5d0a --- /dev/null +++ b/.settings/org.eclipse.wst.jsdt.ui.superType.container @@ -0,0 +1 @@ +org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/.settings/org.eclipse.wst.jsdt.ui.superType.name b/.settings/org.eclipse.wst.jsdt.ui.superType.name new file mode 100644 index 0000000..05bd71b --- /dev/null +++ b/.settings/org.eclipse.wst.jsdt.ui.superType.name @@ -0,0 +1 @@ +Window \ No newline at end of file diff --git a/.settings/org.eclipse.wst.validation.prefs b/.settings/org.eclipse.wst.validation.prefs new file mode 100644 index 0000000..04cad8c --- /dev/null +++ b/.settings/org.eclipse.wst.validation.prefs @@ -0,0 +1,2 @@ +disabled=06target +eclipse.preferences.version=1 diff --git a/.svn/entries b/.svn/entries new file mode 100644 index 0000000..48082f7 --- /dev/null +++ b/.svn/entries @@ -0,0 +1 @@ +12 diff --git a/.svn/format b/.svn/format new file mode 100644 index 0000000..48082f7 --- /dev/null +++ b/.svn/format @@ -0,0 +1 @@ +12 diff --git a/.svn/pristine/01/014c285e56ffc9c0adc485f3391497cbdfc134da.svn-base b/.svn/pristine/01/014c285e56ffc9c0adc485f3391497cbdfc134da.svn-base new file mode 100644 index 0000000..50a3937 --- /dev/null +++ b/.svn/pristine/01/014c285e56ffc9c0adc485f3391497cbdfc134da.svn-base @@ -0,0 +1,232 @@ +package com.ifish.jpush.device; + +import java.lang.reflect.Type; +import java.util.Map; +import java.util.Set; + +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import com.google.gson.reflect.TypeToken; +import com.ifish.jpush.common.ClientConfig; +import com.ifish.jpush.common.ServiceHelper; +import com.ifish.jpush.common.connection.HttpProxy; +import com.ifish.jpush.common.connection.IHttpClient; +import com.ifish.jpush.common.connection.NativeHttpClient; +import com.ifish.jpush.common.resp.APIConnectionException; +import com.ifish.jpush.common.resp.APIRequestException; +import com.ifish.jpush.common.resp.BaseResult; +import com.ifish.jpush.common.resp.BooleanResult; +import com.ifish.jpush.common.resp.DefaultResult; +import com.ifish.jpush.common.resp.ResponseWrapper; +import com.ifish.jpush.utils.Preconditions; + +public class DeviceClient { + + private final NativeHttpClient _httpClient; + private String hostName; + private String devicesPath; + private String tagsPath; + private String aliasesPath; + + public DeviceClient(String masterSecret, String appKey) { + this(masterSecret, appKey, IHttpClient.DEFAULT_MAX_RETRY_TIMES); + } + + public DeviceClient(String masterSecret, String appKey, int maxRetryTimes) { + this(masterSecret, appKey, maxRetryTimes, null); + } + + public DeviceClient(String masterSecret, String appKey, int maxRetryTimes, HttpProxy proxy) { + this(masterSecret, appKey, maxRetryTimes, proxy, ClientConfig.getInstance()); + } + + /** + * + * @param masterSecret API access secret of the appKey. + * @param appKey The KEY of one application on JPush. + * @param maxRetryTimes Max retry times + * @param proxy The proxy, if there is no proxy, should be null. + * @param conf The client configuration. Can use ClientConfig.getInstance() as default. + */ + public DeviceClient(String masterSecret, String appKey, int maxRetryTimes, HttpProxy proxy, ClientConfig conf) { + ServiceHelper.checkBasic(appKey, masterSecret); + + hostName = (String) conf.get(ClientConfig.DEVICE_HOST_NAME); + devicesPath = (String) conf.get(ClientConfig.DEVICES_PATH); + tagsPath = (String) conf.get(ClientConfig.TAGS_PATH); + aliasesPath = (String) conf.get(ClientConfig.ALIASES_PATH); + + String authCode = ServiceHelper.getBasicAuthorization(appKey, masterSecret); + _httpClient = new NativeHttpClient(authCode, maxRetryTimes, proxy); + } + + // -------------- device + + public TagAliasResult getDeviceTagAlias(String registrationId) throws APIConnectionException, APIRequestException { + String url = hostName + devicesPath + "/" + registrationId; + + ResponseWrapper response = _httpClient.sendGet(url); + + return BaseResult.fromResponse(response, TagAliasResult.class); + } + + public DefaultResult updateDeviceTagAlias(String registrationId, boolean clearAlias, boolean clearTag) throws APIConnectionException, APIRequestException { + Preconditions.checkArgument(clearAlias || clearTag, "It is not meaningful to do nothing."); + + String url = hostName + devicesPath + "/" + registrationId; + + JsonObject top = new JsonObject(); + if (clearAlias) { + top.addProperty("alias", ""); + } + if (clearTag) { + top.addProperty("tags", ""); + } + + ResponseWrapper response = _httpClient.sendPost(url, top.toString()); + + return DefaultResult.fromResponse(response); + } + + public DefaultResult updateDeviceTagAlias(String registrationId, String alias, + Set tagsToAdd, Set tagsToRemove) throws APIConnectionException, APIRequestException { + String url = hostName + devicesPath + "/" + registrationId; + + JsonObject top = new JsonObject(); + if (null != alias) { + top.addProperty("alias", alias); + } + + JsonObject tagObject = new JsonObject(); + JsonArray tagsAdd = ServiceHelper.fromSet(tagsToAdd); + if (tagsAdd.size() > 0) { + tagObject.add("add", tagsAdd); + } + + JsonArray tagsRemove = ServiceHelper.fromSet(tagsToRemove); + if (tagsRemove.size() > 0) { + tagObject.add("remove", tagsRemove); + } + + if (tagObject.entrySet().size() > 0) { + top.add("tags", tagObject); + } + + ResponseWrapper response = _httpClient.sendPost(url, top.toString()); + + return DefaultResult.fromResponse(response); + } + + // ------------- tags + + public TagListResult getTagList() throws APIConnectionException, APIRequestException { + String url = hostName + tagsPath + "/"; + + ResponseWrapper response = _httpClient.sendGet(url); + + return TagListResult.fromResponse(response, TagListResult.class); + } + + public BooleanResult isDeviceInTag(String theTag, String registrationID) throws APIConnectionException, APIRequestException { + String url = hostName + tagsPath + "/" + theTag + "/registration_ids/" + registrationID; + ResponseWrapper response = _httpClient.sendGet(url); + + return BaseResult.fromResponse(response, BooleanResult.class); + } + + public DefaultResult addRemoveDevicesFromTag(String theTag, Set toAddUsers, Set toRemoveUsers) throws APIConnectionException, APIRequestException { + String url = hostName + tagsPath + "/" + theTag; + + JsonObject top = new JsonObject(); + JsonObject registrationIds = new JsonObject(); + + if (null != toAddUsers && toAddUsers.size() > 0) { + JsonArray array = new JsonArray(); + for (String user : toAddUsers) { + array.add(new JsonPrimitive(user)); + } + registrationIds.add("add", array); + } + if (null != toRemoveUsers && toRemoveUsers.size() > 0) { + JsonArray array = new JsonArray(); + for (String user : toRemoveUsers) { + array.add(new JsonPrimitive(user)); + } + registrationIds.add("remove", array); + } + + top.add("registration_ids", registrationIds); + + ResponseWrapper response = _httpClient.sendPost(url, top.toString()); + + return DefaultResult.fromResponse(response); + } + + public DefaultResult deleteTag(String theTag, String platform) throws APIConnectionException, APIRequestException { + String url = hostName + tagsPath + "/" + theTag; + if (null != platform) { + url += "?platform=" + platform; + } + + ResponseWrapper response = _httpClient.sendDelete(url); + + return DefaultResult.fromResponse(response); + } + + + // ------------- alias + + public AliasDeviceListResult getAliasDeviceList(String alias, String platform) throws APIConnectionException, APIRequestException { + String url = hostName + aliasesPath + "/" + alias; + if (null != platform) { + url += "?platform=" + platform; + } + + ResponseWrapper response = _httpClient.sendGet(url); + + return BaseResult.fromResponse(response, AliasDeviceListResult.class); + } + + public DefaultResult deleteAlias(String alias, String platform) throws APIConnectionException, APIRequestException { + String url = hostName + aliasesPath + "/" + alias; + if (null != platform) { + url += "?platform=" + platform; + } + + ResponseWrapper response = _httpClient.sendDelete(url); + + return DefaultResult.fromResponse(response); + } + + // -------------- devices status + + public Map getUserOnlineStatus(String... registrationIds) + throws APIConnectionException, APIRequestException + { + Preconditions.checkArgument((null != registrationIds ), + "The registration id list should not be null."); + Preconditions.checkArgument(registrationIds!=null && registrationIds.length > 0 && registrationIds.length <= 1000, + "The length of registration id list should between 1 and 1000."); + + String url = hostName + devicesPath + "/status"; + JsonObject json = new JsonObject(); + JsonArray array = new JsonArray(); + if(registrationIds!=null){ + for(int i = 0; i < registrationIds.length; i++) { + array.add(new JsonPrimitive(registrationIds[i])); + } + } + json.add("registration_ids", array); + Type type = new TypeToken>(){}.getType(); + ResponseWrapper response = _httpClient.sendPost(url, json.toString()); + Map map = new Gson().fromJson(response.responseContent, type); + return map; + } + +} + + + + diff --git a/.svn/pristine/05/05eea6d09259a332395938037b6f17d84ca875bd.svn-base b/.svn/pristine/05/05eea6d09259a332395938037b6f17d84ca875bd.svn-base new file mode 100644 index 0000000..dd943af --- /dev/null +++ b/.svn/pristine/05/05eea6d09259a332395938037b6f17d84ca875bd.svn-base @@ -0,0 +1,8 @@ +package com.ifish.jpush.schedule.model; + +import com.google.gson.JsonElement; + +public interface IModel { + + public JsonElement toJSON(); +} diff --git a/.svn/pristine/06/066a10d0b46c3cabb5ff464a6481b01061a4d152.svn-base b/.svn/pristine/06/066a10d0b46c3cabb5ff464a6481b01061a4d152.svn-base new file mode 100644 index 0000000..61e4f57 --- /dev/null +++ b/.svn/pristine/06/066a10d0b46c3cabb5ff464a6481b01061a4d152.svn-base @@ -0,0 +1,807 @@ +package com.ifish.jpush; + +import java.util.Map; +import java.util.Set; + +import com.google.gson.JsonObject; +import com.ifish.jpush.common.ClientConfig; +import com.ifish.jpush.common.TimeUnit; +import com.ifish.jpush.common.Week; +import com.ifish.jpush.common.connection.HttpProxy; +import com.ifish.jpush.common.resp.APIConnectionException; +import com.ifish.jpush.common.resp.APIRequestException; +import com.ifish.jpush.common.resp.BooleanResult; +import com.ifish.jpush.common.resp.DefaultResult; +import com.ifish.jpush.device.AliasDeviceListResult; +import com.ifish.jpush.device.DeviceClient; +import com.ifish.jpush.device.OnlineStatus; +import com.ifish.jpush.device.TagAliasResult; +import com.ifish.jpush.device.TagListResult; +import com.ifish.jpush.push.PushClient; +import com.ifish.jpush.push.PushResult; +import com.ifish.jpush.push.model.Message; +import com.ifish.jpush.push.model.Platform; +import com.ifish.jpush.push.model.PushPayload; +import com.ifish.jpush.push.model.audience.Audience; +import com.ifish.jpush.push.model.notification.IosAlert; +import com.ifish.jpush.push.model.notification.Notification; +import com.ifish.jpush.report.MessagesResult; +import com.ifish.jpush.report.ReceivedsResult; +import com.ifish.jpush.report.ReportClient; +import com.ifish.jpush.report.UsersResult; +import com.ifish.jpush.schedule.ScheduleClient; +import com.ifish.jpush.schedule.ScheduleListResult; +import com.ifish.jpush.schedule.ScheduleResult; +import com.ifish.jpush.schedule.model.SchedulePayload; +import com.ifish.jpush.schedule.model.TriggerPayload; +import com.ifish.jpush.utils.Preconditions; + + +/** + * The global entrance of JPush API library. + */ +public class JPushClient { + private final PushClient _pushClient; + private final ReportClient _reportClient; + private final DeviceClient _deviceClient; + private final ScheduleClient _scheduleClient; + + /** + * Create a JPush Client. + * + * @param masterSecret API access secret of the appKey. + * @param appKey The KEY of one application on JPush. + */ + public JPushClient(String masterSecret, String appKey) { + _pushClient = new PushClient(masterSecret, appKey); + _reportClient = new ReportClient(masterSecret, appKey); + _deviceClient = new DeviceClient(masterSecret, appKey); + _scheduleClient = new ScheduleClient(masterSecret, appKey); + } + + public JPushClient(String masterSecret, String appKey, int maxRetryTimes) { + _pushClient = new PushClient(masterSecret, appKey, maxRetryTimes); + _reportClient = new ReportClient(masterSecret, appKey, maxRetryTimes); + _deviceClient = new DeviceClient(masterSecret, appKey, maxRetryTimes); + _scheduleClient = new ScheduleClient(masterSecret, appKey, maxRetryTimes); + } + + public JPushClient(String masterSecret, String appKey, int maxRetryTimes, HttpProxy proxy) { + _pushClient = new PushClient(masterSecret, appKey, maxRetryTimes, proxy); + _reportClient = new ReportClient(masterSecret, appKey, maxRetryTimes, proxy); + _deviceClient = new DeviceClient(masterSecret, appKey, maxRetryTimes, proxy); + _scheduleClient = new ScheduleClient(masterSecret, appKey, maxRetryTimes, proxy); + } + + /** + * Create a JPush Client by custom Client configuration. + * + * If you are using JPush privacy cloud, maybe this constructor is what you needed. + * + * @param masterSecret API access secret of the appKey. + * @param appKey The KEY of one application on JPush. + * @param maxRetryTimes Client request retry times. + * @param proxy The proxy, if there is no proxy, should be null. + * @param conf The client configuration. Can use ClientConfig.getInstance() as default. + */ + public JPushClient(String masterSecret, String appKey, int maxRetryTimes, HttpProxy proxy, ClientConfig conf) { + _pushClient = new PushClient(masterSecret, appKey, maxRetryTimes, proxy, conf); + _reportClient = new ReportClient(masterSecret, appKey, maxRetryTimes, proxy, conf); + _deviceClient = new DeviceClient(masterSecret, appKey, maxRetryTimes, proxy, conf); + _scheduleClient = new ScheduleClient(masterSecret, appKey, maxRetryTimes, proxy, conf); + } + + /** + * Create a JPush Client by custom Client configuration with global settings. + * + * If you are using JPush privacy cloud, and you want different settings from default globally, + * maybe this constructor is what you needed. + * + * @param masterSecret API access secret of the appKey. + * @param appKey The KEY of one application on JPush. + * @param maxRetryTimes Client request retry times. + * @param proxy The proxy, if there is no proxy, should be null. + * @param conf The client configuration. Can use ClientConfig.getInstance() as default. + * @param apnsProduction Global APNs environment setting. It will override PushPayload Options. + * @param timeToLive Global time_to_live setting. It will override PushPayload Options. + */ + public JPushClient(String masterSecret, String appKey, int maxRetryTimes, HttpProxy proxy, ClientConfig conf, + boolean apnsProduction, long timeToLive) { + _pushClient = new PushClient(masterSecret, appKey, maxRetryTimes, proxy, conf); + _reportClient = new ReportClient(masterSecret, appKey, maxRetryTimes, proxy, conf); + _deviceClient = new DeviceClient(masterSecret, appKey, maxRetryTimes, proxy, conf); + _scheduleClient = new ScheduleClient(masterSecret, appKey, maxRetryTimes, proxy, conf); + _pushClient.setDefaults(apnsProduction, timeToLive); + } + + /** + * Create a JPush Client with global settings. + * + * If you want different settings from default globally, this constructor is what you needed. + * + * @param masterSecret API access secret of the appKey. + * @param appKey The KEY of one application on JPush. + * @param apnsProduction Global APNs environment setting. It will override PushPayload Options. + * @param timeToLive Global time_to_live setting. It will override PushPayload Options. + */ + public JPushClient(String masterSecret, String appKey, boolean apnsProduction, long timeToLive) { + _pushClient = new PushClient(masterSecret, appKey, apnsProduction, timeToLive); + _reportClient = new ReportClient(masterSecret, appKey); + _deviceClient = new DeviceClient(masterSecret, appKey); + _scheduleClient = new ScheduleClient(masterSecret, appKey); + } + + + // ----------------------------- Push API + + /** + * Send a push with PushPayload object. + * + * @param pushPayload payload object of a push. + * @return PushResult The result object of a Push. Can be printed to a JSON. + * @throws APIConnectionException + * @throws APIRequestException + */ + public PushResult sendPush(PushPayload pushPayload) throws APIConnectionException, APIRequestException { + return _pushClient.sendPush(pushPayload); + } + + /** + * Send a push with JSON string. + * + * You can send a push JSON string directly with this method. + * + * Attention: globally settings cannot be affect this type of Push. + * + * @param payloadString payload of a push. + * @return PushResult. Can be printed to a JSON. + * @throws APIConnectionException + * @throws APIRequestException + */ + public PushResult sendPush(String payloadString) throws APIConnectionException, APIRequestException { + return _pushClient.sendPush(payloadString); + } + + /** + * Validate a push action, but do NOT send it actually. + * + * @param paylaod + * @return + * @throws APIConnectionException + * @throws APIRequestException + */ + public PushResult sendPushValidate(PushPayload paylaod) throws APIConnectionException, APIRequestException { + return _pushClient.sendPushValidate(paylaod); + } + + public PushResult sendPushValidate(String payloadString) throws APIConnectionException, APIRequestException { + return _pushClient.sendPushValidate(payloadString); + } + + + // ------------------------------- Report API + + /** + * Get received report. + * + * @param msgIds 100 msgids to batch getting is supported. + * @return ReceivedResult. Can be printed to JSON. + * @throws APIConnectionException + * @throws APIRequestException + */ + public ReceivedsResult getReportReceiveds(String msgIds) throws APIConnectionException, APIRequestException { + return _reportClient.getReceiveds(msgIds); + } + + public UsersResult getReportUsers(TimeUnit timeUnit, String start, int duration) throws APIConnectionException, APIRequestException { + return _reportClient.getUsers(timeUnit, start, duration); + } + + public MessagesResult getReportMessages(String msgIds) throws APIConnectionException, APIRequestException { + return _reportClient.getMessages(msgIds); + } + + + // ------------------------------ Shortcuts - notification + + /** + * Shortcut + */ + public PushResult sendNotificationAll(String alert) throws APIConnectionException, APIRequestException { + PushPayload payload = PushPayload.alertAll(alert); + return _pushClient.sendPush(payload); + } + + /** + * Shortcut + */ + public PushResult sendAndroidNotificationWithAlias(String title, String alert, + Map extras, String... alias) + throws APIConnectionException, APIRequestException { + PushPayload payload = PushPayload.newBuilder() + .setPlatform(Platform.android()) + .setAudience(Audience.alias(alias)) + .setNotification(Notification.android(alert, title, extras)) + .build(); + return _pushClient.sendPush(payload); + } + + /** + * Shortcut + */ + public PushResult sendAndroidNotificationWithRegistrationID(String title, String alert, + Map extras, String... registrationID) + throws APIConnectionException, APIRequestException { + PushPayload payload = PushPayload.newBuilder() + .setPlatform(Platform.android()) + .setAudience(Audience.registrationId(registrationID)) + .setNotification(Notification.android(alert, title, extras)) + .build(); + return _pushClient.sendPush(payload); + } + + /** + * Shortcut + */ + public PushResult sendIosNotificationWithAlias(String alert, Map extras, String... alias) + throws APIConnectionException, APIRequestException { + PushPayload payload = PushPayload.newBuilder() + .setPlatform(Platform.ios()) + .setAudience(Audience.alias(alias)) + .setNotification(Notification.ios(alert, extras)) + .build(); + return _pushClient.sendPush(payload); + } + + /** + * Send an iOS notification with alias. + * If you want to send alert as a Json object, maybe this method is what you needed. + * + * @param alert The wrapper of APNs alert. + * @param extras The extra params. + * @param alias The alias list. + * @return + * @throws APIConnectionException + * @throws APIRequestException + */ + public PushResult sendIosNotificationWithAlias(IosAlert alert, Map extras, String... alias) + throws APIConnectionException, APIRequestException { + PushPayload payload = PushPayload.newBuilder() + .setPlatform(Platform.ios()) + .setAudience(Audience.alias(alias)) + .setNotification(Notification.ios(alert, extras)) + .build(); + return _pushClient.sendPush(payload); + } + + /** + * Send an iOS notification with alias. + * If you want to send alert as a Json object, maybe this method is what you needed. + * + * @param alert The wrapper of APNs alert. + * @param extras The extra params. + * @param alias The alias list. + * @return + * @throws APIConnectionException + * @throws APIRequestException + */ + public PushResult sendIosNotificationWithAlias(JsonObject alert, Map extras, String... alias) + throws APIConnectionException, APIRequestException { + PushPayload payload = PushPayload.newBuilder() + .setPlatform(Platform.ios()) + .setAudience(Audience.alias(alias)) + .setNotification(Notification.ios(alert, extras)) + .build(); + return _pushClient.sendPush(payload); + } + + /** + * Shortcut + */ + public PushResult sendIosNotificationWithRegistrationID(String alert, + Map extras, String... registrationID) + throws APIConnectionException, APIRequestException { + PushPayload payload = PushPayload.newBuilder() + .setPlatform(Platform.ios()) + .setAudience(Audience.registrationId(registrationID)) + .setNotification(Notification.ios(alert, extras)) + .build(); + return _pushClient.sendPush(payload); + } + + /** + * Send an iOS notification with registrationIds. + * If you want to send alert as a Json object, maybe this method is what you needed. + * + * @param alert The wrapper of APNs alert. + * @param extras The extra params. + * @param registrationID The registration ids. + * @return + * @throws APIConnectionException + * @throws APIRequestException + */ + public PushResult sendIosNotificationWithRegistrationID(IosAlert alert, + Map extras, String... registrationID) + throws APIConnectionException, APIRequestException { + PushPayload payload = PushPayload.newBuilder() + .setPlatform(Platform.ios()) + .setAudience(Audience.registrationId(registrationID)) + .setNotification(Notification.ios(alert, extras)) + .build(); + return _pushClient.sendPush(payload); + } + + /** + * Send an iOS notification with registrationIds. + * If you want to send alert as a Json object, maybe this method is what you needed. + * + * @param alert The wrapper of APNs alert. + * @param extras The extra params. + * @param registrationID The registration ids. + * @return + * @throws APIConnectionException + * @throws APIRequestException + */ + public PushResult sendIosNotificationWithRegistrationID(JsonObject alert, + Map extras, String... registrationID) + throws APIConnectionException, APIRequestException { + PushPayload payload = PushPayload.newBuilder() + .setPlatform(Platform.ios()) + .setAudience(Audience.registrationId(registrationID)) + .setNotification(Notification.ios(alert, extras)) + .build(); + return _pushClient.sendPush(payload); + } + + + // ---------------------- shortcuts - message + + /** + * Shortcut + */ + public PushResult sendMessageAll(String msgContent) throws APIConnectionException, APIRequestException { + PushPayload payload = PushPayload.messageAll(msgContent); + return _pushClient.sendPush(payload); + } + + /** + * Shortcut + */ + public PushResult sendAndroidMessageWithAlias(String title, String msgContent, String... alias) + throws APIConnectionException, APIRequestException { + PushPayload payload = PushPayload.newBuilder() + .setPlatform(Platform.android()) + .setAudience(Audience.alias(alias)) + .setMessage(Message.newBuilder() + .setTitle(title) + .setMsgContent(msgContent) + .build()) + .build(); + return _pushClient.sendPush(payload); + } + + /** + * Shortcut + */ + public PushResult sendAndroidMessageWithRegistrationID(String title, String msgContent, String... registrationID) + throws APIConnectionException, APIRequestException { + PushPayload payload = PushPayload.newBuilder() + .setPlatform(Platform.android()) + .setAudience(Audience.registrationId(registrationID)) + .setMessage(Message.newBuilder() + .setTitle(title) + .setMsgContent(msgContent) + .build()) + .build(); + return _pushClient.sendPush(payload); + } + + /** + * Shortcut + */ + public PushResult sendIosMessageWithAlias(String title, String msgContent, String... alias) + throws APIConnectionException, APIRequestException { + PushPayload payload = PushPayload.newBuilder() + .setPlatform(Platform.ios()) + .setAudience(Audience.alias(alias)) + .setMessage(Message.newBuilder() + .setTitle(title) + .setMsgContent(msgContent) + .build()) + .build(); + return _pushClient.sendPush(payload); + } + + /** + * Shortcut + */ + public PushResult sendIosMessageWithRegistrationID(String title, String msgContent, String... registrationID) + throws APIConnectionException, APIRequestException { + PushPayload payload = PushPayload.newBuilder() + .setPlatform(Platform.ios()) + .setAudience(Audience.registrationId(registrationID)) + .setMessage(Message.newBuilder() + .setTitle(title) + .setMsgContent(msgContent) + .build()) + .build(); + return _pushClient.sendPush(payload); + } + + /** + * Shortcut + */ + public PushResult sendMessageWithRegistrationID(String title, String msgContent, String... registrationID) + throws APIConnectionException, APIRequestException { + PushPayload payload = PushPayload.newBuilder() + .setPlatform(Platform.all()) + .setAudience(Audience.registrationId(registrationID)) + .setMessage(Message.newBuilder() + .setTitle(title) + .setMsgContent(msgContent) + .build()) + .build(); + return _pushClient.sendPush(payload); + } + + + + // ----------------------- Device + + public TagAliasResult getDeviceTagAlias(String registrationId) + throws APIConnectionException, APIRequestException { + return _deviceClient.getDeviceTagAlias(registrationId); + } + + public DefaultResult updateDeviceTagAlias(String registrationId, boolean clearAlias, boolean clearTag) + throws APIConnectionException, APIRequestException { + return _deviceClient.updateDeviceTagAlias(registrationId, clearAlias, clearTag); + } + + public DefaultResult updateDeviceTagAlias(String registrationId, String alias, + Set tagsToAdd, Set tagsToRemove) + throws APIConnectionException, APIRequestException { + return _deviceClient.updateDeviceTagAlias(registrationId, alias, tagsToAdd, tagsToRemove); + } + + public TagListResult getTagList() + throws APIConnectionException, APIRequestException { + return _deviceClient.getTagList(); + } + + public BooleanResult isDeviceInTag(String theTag, String registrationID) + throws APIConnectionException, APIRequestException { + return _deviceClient.isDeviceInTag(theTag, registrationID); + } + + public DefaultResult addRemoveDevicesFromTag(String theTag, + Set toAddUsers, Set toRemoveUsers) + throws APIConnectionException, APIRequestException { + return _deviceClient.addRemoveDevicesFromTag(theTag, toAddUsers, + toRemoveUsers); + } + + public DefaultResult deleteTag(String theTag, String platform) + throws APIConnectionException, APIRequestException { + return _deviceClient.deleteTag(theTag, platform); + } + + public AliasDeviceListResult getAliasDeviceList(String alias, + String platform) throws APIConnectionException, APIRequestException { + return _deviceClient.getAliasDeviceList(alias, platform); + } + + public DefaultResult deleteAlias(String alias, String platform) + throws APIConnectionException, APIRequestException { + return _deviceClient.deleteAlias(alias, platform); + } + + public Map getUserOnlineStatus(String... registrationIds) + throws APIConnectionException, APIRequestException + { + return _deviceClient.getUserOnlineStatus(registrationIds); + } + + // ----------------------- Schedule + + /** + * Create a single schedule. + * @param name The schedule name. + * @param time The push time, format is 'yyyy-MM-dd HH:mm:ss' + * @param push The push payload. + * @return The created scheduleResult instance. + * @throws APIConnectionException + * @throws APIRequestException + */ + public ScheduleResult createSingleSchedule(String name, String time, PushPayload push) + throws APIConnectionException, APIRequestException { + TriggerPayload trigger = TriggerPayload.newBuilder() + .setSingleTime(time) + .buildSingle(); + SchedulePayload payload = SchedulePayload.newBuilder() + .setName(name) + .setEnabled(true) + .setTrigger(trigger) + .setPush(push) + .build(); + + return _scheduleClient.createSchedule(payload); + } + + /** + * Create a daily schedule push everyday. + * @param name The schedule name. + * @param start The schedule comes into effect date, format 'yyyy-MM-dd HH:mm:ss'. + * @param end The schedule expiration date, format 'yyyy-MM-dd HH:mm:ss'. + * @param time The push time, format 'HH:mm:ss' + * @param push The push payload. + * @return The created scheduleResult instance. + * @throws APIConnectionException + * @throws APIRequestException + */ + public ScheduleResult createDailySchedule(String name, String start, String end, String time, PushPayload push) + throws APIConnectionException, APIRequestException { + return createPeriodicalSchedule(name, start, end, time, TimeUnit.DAY, 1, null, push); + } + + /** + * Create a daily schedule push with a custom frequency. + * @param name The schedule name. + * @param start The schedule comes into effect date, format 'yyyy-MM-dd HH:mm:ss'. + * @param end The schedule expiration date, format 'yyyy-MM-dd HH:mm:ss'. + * @param time The push time, format 'HH:mm:ss' + * @param frequency The custom frequency. + * @param push The push payload. + * @return The created scheduleResult instance. + * @throws APIConnectionException + * @throws APIRequestException + */ + public ScheduleResult createDailySchedule(String name, String start, String end, String time, int frequency, PushPayload push) + throws APIConnectionException, APIRequestException { + return createPeriodicalSchedule(name, start, end, time, TimeUnit.DAY, frequency, null, push); + } + + /** + * Create a weekly schedule push every week at the appointed days. + * @param name The schedule name. + * @param start The schedule comes into effect date, format 'yyyy-MM-dd HH:mm:ss'. + * @param end The schedule expiration date, format 'yyyy-MM-dd HH:mm:ss'. + * @param time The push time, format 'HH:mm:ss' + * @param days The appointed days. + * @param push The push payload. + * @return The created scheduleResult instance. + * @throws APIConnectionException + * @throws APIRequestException + */ + public ScheduleResult createWeeklySchedule(String name, String start, String end, String time, Week[] days, PushPayload push) + throws APIConnectionException, APIRequestException { + Preconditions.checkArgument(null != days && days.length > 0, "The days must not be empty."); + + String[] points = new String[days.length]; + for(int i = 0 ; i < days.length; i++) { + points[i] = days[i].name(); + } + return createPeriodicalSchedule(name, start, end, time, TimeUnit.WEEK, 1, points, push); + } + + /** + * Create a weekly schedule push with a custom frequency at the appointed days. + * @param name The schedule name. + * @param start The schedule comes into effect date, format 'yyyy-MM-dd HH:mm:ss'. + * @param end The schedule expiration date, format 'yyyy-MM-dd HH:mm:ss'. + * @param time The push time, format 'HH:mm:ss'. + * @param frequency The custom frequency. + * @param days The appointed days. + * @param push The push payload. + * @return The created scheduleResult instance. + * @throws APIConnectionException + * @throws APIRequestException + */ + public ScheduleResult createWeeklySchedule(String name, String start, String end, String time, int frequency, Week[] days, PushPayload push) + throws APIConnectionException, APIRequestException { + Preconditions.checkArgument(null != days && days.length > 0, "The days must not be empty."); + + String[] points = new String[days.length]; + for(int i = 0 ; i < days.length; i++) { + points[i] = days[i].name(); + } + return createPeriodicalSchedule(name, start, end, time, TimeUnit.WEEK, frequency, points, push); + } + + /** + * Create a monthly schedule push every month at the appointed days. + * @param name The schedule name. + * @param start The schedule comes into effect date, format 'yyyy-MM-dd HH:mm:ss'. + * @param end The schedule expiration date, format 'yyyy-MM-dd HH:mm:ss'. + * @param time The push time, format 'HH:mm:ss'. + * @param points The appointed days. + * @param push The push payload. + * @return The created scheduleResult instance. + * @throws APIConnectionException + * @throws APIRequestException + */ + public ScheduleResult createMonthlySchedule(String name, String start, String end, String time, String[] points, PushPayload push) + throws APIConnectionException, APIRequestException { + Preconditions.checkArgument(null != points && points.length > 0, "The points must not be empty."); + return createPeriodicalSchedule(name, start, end, time, TimeUnit.MONTH, 1, points, push); + } + + /** + * Create a monthly schedule push with a custom frequency at the appointed days. + * @param name The schedule name. + * @param start The schedule comes into effect date, format 'yyyy-MM-dd HH:mm:ss'. + * @param end The schedule expiration date, format 'yyyy-MM-dd HH:mm:ss'. + * @param time The push time, format 'HH:mm:ss'. + * @param frequency The custom frequency. + * @param points The appointed days. + * @param push The push payload. + * @return The created scheduleResult instance. + * @throws APIConnectionException + * @throws APIRequestException + */ + public ScheduleResult createMonthlySchedule(String name, String start, String end, String time, int frequency, String[] points, PushPayload push) + throws APIConnectionException, APIRequestException { + Preconditions.checkArgument(null != points && points.length > 0, "The points must not be empty."); + return createPeriodicalSchedule(name, start, end, time, TimeUnit.MONTH, frequency, points, push); + } + + /** + * Get the schedule information by the schedule id. + * @param scheduleId The schedule id. + * @return The schedule information. + * @throws APIConnectionException + * @throws APIRequestException + */ + public ScheduleResult getSchedule(String scheduleId) + throws APIConnectionException, APIRequestException { + return _scheduleClient.getSchedule(scheduleId); + } + + /** + * Get the schedule list size and the first page. + * @return The schedule list size and the first page. + * @throws APIConnectionException + * @throws APIRequestException + */ + public ScheduleListResult getScheduleList() + throws APIConnectionException, APIRequestException { + return _scheduleClient.getScheduleList(1); + } + + /** + * Get the schedule list by the page. + * @param page The page to search. + * @return The schedule list of the appointed page. + * @throws APIConnectionException + * @throws APIRequestException + */ + public ScheduleListResult getScheduleList(int page) + throws APIConnectionException, APIRequestException { + return _scheduleClient.getScheduleList(page); + } + + /** + * Update the schedule name + * @param scheduleId The schedule id. + * @param name The new name. + * @return The schedule information after updated. + * @throws APIConnectionException + * @throws APIRequestException + */ + public ScheduleResult updateScheduleName(String scheduleId, String name) + throws APIConnectionException, APIRequestException { + SchedulePayload payload = SchedulePayload.newBuilder() + .setName(name) + .build(); + + return updateSchedule(scheduleId, payload); + } + + /** + * Enable the schedule. + * @param scheduleId The schedule id. + * @return The schedule information after updated. + * @throws APIConnectionException + * @throws APIRequestException + */ + public ScheduleResult enableSchedule(String scheduleId) + throws APIConnectionException, APIRequestException { + SchedulePayload payload = SchedulePayload.newBuilder() + .setEnabled(true) + .build(); + + return updateSchedule(scheduleId, payload); + } + + /** + * Disable the schedule. + * @param scheduleId The schedule id. + * @return The schedule information after updated. + * @throws APIConnectionException + * @throws APIRequestException + */ + public ScheduleResult disableSchedule(String scheduleId) + throws APIConnectionException, APIRequestException { + SchedulePayload payload = SchedulePayload.newBuilder() + .setEnabled(false) + .build(); + return updateSchedule(scheduleId, payload); + } + + /** + * Update the trigger of the schedule. + * @param scheduleId The schedule id. + * @param trigger The new trigger. + * @return The schedule information after updated. + * @throws APIConnectionException + * @throws APIRequestException + */ + public ScheduleResult updateScheduleTrigger(String scheduleId, TriggerPayload trigger) + throws APIConnectionException, APIRequestException { + SchedulePayload payload = SchedulePayload.newBuilder() + .setTrigger(trigger) + .build(); + + return updateSchedule(scheduleId, payload); + } + + /** + * Update the push content of the schedule. + * @param scheduleId The schedule id. + * @param push The new push payload. + * @return The schedule information after updated. + * @throws APIConnectionException + * @throws APIRequestException + */ + public ScheduleResult updateSchedulePush(String scheduleId, PushPayload push) + throws APIConnectionException, APIRequestException { + SchedulePayload payload = SchedulePayload.newBuilder() + .setPush(push) + .build(); + + return updateSchedule(scheduleId, payload); + } + + /** + * Update a schedule by the id. + * @param scheduleId The schedule id to update. + * @param payload The new schedule payload. + * @return The new schedule information. + * @throws APIConnectionException + * @throws APIRequestException + */ + public ScheduleResult updateSchedule(String scheduleId, SchedulePayload payload) + throws APIConnectionException, APIRequestException { + return _scheduleClient.updateSchedule(scheduleId, payload); + } + + /** + * Delete a schedule by id. + * @param scheduleId The schedule id. + * @throws APIConnectionException + * @throws APIRequestException + */ + public void deleteSchedule(String scheduleId) + throws APIConnectionException, APIRequestException { + _scheduleClient.deleteSchedule(scheduleId); + } + + private ScheduleResult createPeriodicalSchedule(String name, String start, String end, String time, + TimeUnit timeUnit, int frequency, String[] point, PushPayload push) + throws APIConnectionException, APIRequestException { + TriggerPayload trigger = TriggerPayload.newBuilder() + .setPeriodTime(start, end, time) + .setTimeFrequency(timeUnit, frequency, point ) + .buildPeriodical(); + SchedulePayload payload = SchedulePayload.newBuilder() + .setName(name) + .setEnabled(true) + .setTrigger(trigger) + .setPush(push) + .build(); + + return _scheduleClient.createSchedule(payload); + } + +} + diff --git a/.svn/pristine/06/0670e10aedb86bac446c59432ada5601223815f2.svn-base b/.svn/pristine/06/0670e10aedb86bac446c59432ada5601223815f2.svn-base new file mode 100644 index 0000000..5c38a9e --- /dev/null +++ b/.svn/pristine/06/0670e10aedb86bac446c59432ada5601223815f2.svn-base @@ -0,0 +1,14 @@ +package com.ifish.jpush.device; + +import java.util.ArrayList; +import java.util.List; + +import com.google.gson.annotations.Expose; +import com.ifish.jpush.common.resp.BaseResult; + +public class TagListResult extends BaseResult { + + @Expose public List tags = new ArrayList(); + +} + diff --git a/.svn/pristine/0d/0d84aede8324ce45a800a6ef72012e22e648ddf5.svn-base b/.svn/pristine/0d/0d84aede8324ce45a800a6ef72012e22e648ddf5.svn-base new file mode 100644 index 0000000..b604f13 --- /dev/null +++ b/.svn/pristine/0d/0d84aede8324ce45a800a6ef72012e22e648ddf5.svn-base @@ -0,0 +1,42 @@ + + + quartzPro + + + + + + org.eclipse.wst.jsdt.core.javascriptValidator + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.wst.common.project.facet.core.builder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + org.eclipse.wst.validation.validationbuilder + + + + + + org.eclipse.jem.workbench.JavaEMFNature + org.eclipse.wst.common.modulecore.ModuleCoreNature + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + org.eclipse.wst.common.project.facet.core.nature + org.eclipse.wst.jsdt.core.jsNature + + diff --git a/.svn/pristine/10/10833f3152744e7426e56fa1d3138fdc51e9037a.svn-base b/.svn/pristine/10/10833f3152744e7426e56fa1d3138fdc51e9037a.svn-base new file mode 100644 index 0000000..2cdbb46 --- /dev/null +++ b/.svn/pristine/10/10833f3152744e7426e56fa1d3138fdc51e9037a.svn-base @@ -0,0 +1,16 @@ +package com.ifish.jpush.utils; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Copied from javax.annotation.Nullable + */ +@Documented +//@TypeQualifierNickname +//@Nonnull(when = When.UNKNOWN) +@Retention(RetentionPolicy.RUNTIME) +public @interface Nullable { + +} diff --git a/.svn/pristine/16/168a53b37b801adf8a1a0bdd9c8b76aa2b95fb16.svn-base b/.svn/pristine/16/168a53b37b801adf8a1a0bdd9c8b76aa2b95fb16.svn-base new file mode 100644 index 0000000..8b2376a --- /dev/null +++ b/.svn/pristine/16/168a53b37b801adf8a1a0bdd9c8b76aa2b95fb16.svn-base @@ -0,0 +1,31 @@ +package com.ifish.jpush.device; + +public class OnlineStatus { + + Boolean online; + String last_online_time; + + public Boolean getOnline() { + return online; + } + + public void setOnline(Boolean online) { + this.online = online; + } + + public String getLast_online_time() { + return last_online_time; + } + + public void setLast_online_time(String last_online_time) { + this.last_online_time = last_online_time; + } + + @Override + public String toString() { + if(null == last_online_time) { + return "status: " + online; + } + return "status: " + online + " , last_online_time: " + last_online_time; + } +} diff --git a/.svn/pristine/17/177a9d61f0e894f130d7fa4ebc42a895afe1ed4f.svn-base b/.svn/pristine/17/177a9d61f0e894f130d7fa4ebc42a895afe1ed4f.svn-base new file mode 100644 index 0000000..081be1a --- /dev/null +++ b/.svn/pristine/17/177a9d61f0e894f130d7fa4ebc42a895afe1ed4f.svn-base @@ -0,0 +1,19 @@ +package com.ifish.jpush.push.model.audience; + +public enum AudienceType { + TAG("tag"), + TAG_AND("tag_and"), + ALIAS("alias"), + SEGMENT("segment"), + REGISTRATION_ID("registration_id"); + + private final String value; + private AudienceType(final String value) { + this.value = value; + } + public String value() { + return this.value; + } + + +} diff --git a/.svn/pristine/1d/1d2f478e995d4035e76c986b717e618908578a74.svn-base b/.svn/pristine/1d/1d2f478e995d4035e76c986b717e618908578a74.svn-base new file mode 100644 index 0000000..6ddb7e2 --- /dev/null +++ b/.svn/pristine/1d/1d2f478e995d4035e76c986b717e618908578a74.svn-base @@ -0,0 +1,40 @@ +package com.ifish.jpush.common.resp; + +/** + * Should retry for encountering this exception basically. + * Normally it is due to: + * 1. Connect timed out. + * 2. Read timed out. + * 3. Cannot parse domain. + * + * For Push action, if the exception is "Read timed out" you may not want to retry it. + */ +public class APIConnectionException extends Exception { + private static final long serialVersionUID = -2615370590441195647L; + private boolean readTimedout = false; + private int doneRetriedTimes = 0; + + public APIConnectionException(String message, Throwable e) { + super(message, e); + } + + public APIConnectionException(String message, Throwable e, int doneRetriedTimes) { + super(message, e); + this.doneRetriedTimes = doneRetriedTimes; + } + + public APIConnectionException(String message, Throwable e, boolean readTimedout) { + super(message, e); + this.readTimedout = readTimedout; + } + + public boolean isReadTimedout() { + return readTimedout; + } + + public int getDoneRetriedTimes() { + return this.doneRetriedTimes; + } +} + + diff --git a/.svn/pristine/1d/1d5448f4b925ebd0d99ee469e946847c64a8a81e.svn-base b/.svn/pristine/1d/1d5448f4b925ebd0d99ee469e946847c64a8a81e.svn-base new file mode 100644 index 0000000..57fc477 --- /dev/null +++ b/.svn/pristine/1d/1d5448f4b925ebd0d99ee469e946847c64a8a81e.svn-base @@ -0,0 +1,175 @@ +package com.ifish.jpush.schedule.model; + +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import com.ifish.jpush.common.TimeUnit; +import com.ifish.jpush.utils.Preconditions; +import com.ifish.jpush.utils.StringUtils; +import com.ifish.jpush.utils.TimeUtils; + + +public class TriggerPayload implements IModel { + + private static Gson gson = new Gson(); + + private Type type; + + private String start; + private String end; + private String time; + private TimeUnit time_unit; + private int frequency; + private String[] point; + + private TriggerPayload(String time) { + this.type = Type.single; + this.time = time; + } + + private TriggerPayload(String start, String end, String time, TimeUnit time_unit, int frequency, String[] point) { + this.type = Type.periodical; + this.start = start; + this.end = end; + this.time = time; + this.time_unit = time_unit; + this.frequency = frequency; + this.point = point; + } + + public static Builder newBuilder() { + return new Builder(); + } + + @Override + public String toString() { + return gson.toJson(toJSON()); + } + + @Override + public JsonElement toJSON() { + JsonObject json = new JsonObject(); + switch (type) { + case single: + JsonObject s = new JsonObject(); + s.addProperty("time", time); + json.add(Type.single.name(), s); + break; + case periodical: + JsonObject p = new JsonObject(); + p.addProperty("start", start); + p.addProperty("end", end); + p.addProperty("time", time); + p.addProperty("time_unit", time_unit.name().toLowerCase()); + p.addProperty("frequency", frequency); + if( !TimeUnit.DAY.equals(time_unit) ) { + JsonArray array = new JsonArray(); + for (String aPoint : point) { + array.add(new JsonPrimitive(aPoint)); + } + p.add("point", array); + } + json.add(Type.periodical.name(), p); + break; + default: + // nothing + } + return json; + } + + public static enum Type { + single, periodical + } + + public static class Builder{ + + private String start; + private String end; + private String time; + private TimeUnit time_unit; + private int frequency; + private String[] point; + + /** + * Setup time for single trigger. + * @param time The execute time, format yyyy-MM-dd HH:mm:ss + * @return this Builder + */ + public Builder setSingleTime(String time) { + this.time = time; + return this; + } + + + /** + * Setup period for periodical trigger. + * @param start The start time, format yyyy-MM-dd HH:mm:ss + * @param end The end time, format yyyy-MM-dd HH:mm:ss + * @param time The execute time, format HH:mm:ss + * @return this Builder + */ + public Builder setPeriodTime(String start, String end, String time) { + this.start = start; + this.end = end; + this.time = time; + return this; + } + + /** + * Setup frequency for periodical trigger. + * @param time_unit The time unit, can be day, week or month. + * @param frequency The frequency cooperate with time unit, must between 1 and 100. + * @param point The time point cooperate with time unit. + * If time unit is day, the point should be null. + * If time unit is week, should be the abbreviation of the days. eg. {"MON", "TUE"} + * If time unit is month, should be the date of the days. eg. {"01", "03"} + * @return this Builder + */ + public Builder setTimeFrequency(TimeUnit time_unit, int frequency, String[] point) { + this.time_unit = time_unit; + this.frequency = frequency; + this.point = point; + return this; + } + + public TriggerPayload buildSingle() { + Preconditions.checkArgument(StringUtils.isNotEmpty(time), "The time must not be empty."); + Preconditions.checkArgument(TimeUtils.isDateFormat(time), "The time format is incorrect."); + return new TriggerPayload(time); + } + + public TriggerPayload buildPeriodical() { + Preconditions.checkArgument(StringUtils.isNotEmpty(start), "The start must not be empty."); + Preconditions.checkArgument(StringUtils.isNotEmpty(end), "The end must not be empty."); + Preconditions.checkArgument(StringUtils.isNotEmpty(time), "The time must not be empty."); + + Preconditions.checkArgument(TimeUtils.isDateFormat(start), "The start format is incorrect."); + Preconditions.checkArgument(TimeUtils.isDateFormat(end), "The end format is incorrect."); + Preconditions.checkArgument(TimeUtils.isTimeFormat(time), "The time format is incorrect."); + + Preconditions.checkNotNull(time_unit, "The time_unit must not be null."); + Preconditions.checkArgument(isTimeUnitOk(time_unit), "The time unit must be DAY, WEEK or MONTH."); + + Preconditions.checkArgument(frequency > 0 && frequency < 101, "The frequency must be a int between 1 and 100."); + + return new TriggerPayload(start, end, time, time_unit, frequency, point); + } + + private boolean isTimeUnitOk(TimeUnit timeUnit) { + switch (timeUnit) { + case HOUR: + return false; + case DAY: + case WEEK: + case MONTH: + return true; + default: + return false; + } + } + + } + +} diff --git a/.svn/pristine/2e/2e3ccf7cbc4efb3322f740f018974df19ea7204f.svn-base b/.svn/pristine/2e/2e3ccf7cbc4efb3322f740f018974df19ea7204f.svn-base new file mode 100644 index 0000000..83e47c3 --- /dev/null +++ b/.svn/pristine/2e/2e3ccf7cbc4efb3322f740f018974df19ea7204f.svn-base @@ -0,0 +1,85 @@ + + + + + + + + + + + + + true + + + + + + + + + + + + + 0 0 10 * * ? + + + + + + + + + + + pushRemind + + + + + + + + + + + + + + + + + ${jpush.ios.appKey} + + + + ${jpush.ios.secret} + + + + ${jpush.ios.productionMode} + + + + + + + ${netease.appKey} + + + + ${netease.appSecret} + + + \ No newline at end of file diff --git a/.svn/pristine/33/33d89a245bca7fd664198dc683fdaf532c69b9d3.svn-base b/.svn/pristine/33/33d89a245bca7fd664198dc683fdaf532c69b9d3.svn-base new file mode 100644 index 0000000..d861403 --- /dev/null +++ b/.svn/pristine/33/33d89a245bca7fd664198dc683fdaf532c69b9d3.svn-base @@ -0,0 +1,168 @@ +package com.ifish.jpush.push; + +import com.google.gson.JsonParseException; +import com.google.gson.JsonParser; +import com.ifish.jpush.common.ClientConfig; +import com.ifish.jpush.common.ServiceHelper; +import com.ifish.jpush.common.connection.HttpProxy; +import com.ifish.jpush.common.connection.IHttpClient; +import com.ifish.jpush.common.connection.NativeHttpClient; +import com.ifish.jpush.common.resp.APIConnectionException; +import com.ifish.jpush.common.resp.APIRequestException; +import com.ifish.jpush.common.resp.BaseResult; +import com.ifish.jpush.common.resp.ResponseWrapper; +import com.ifish.jpush.push.model.PushPayload; +import com.ifish.jpush.utils.Preconditions; +import com.ifish.jpush.utils.StringUtils; + + +/** + * Entrance for sending Push. + * + * For the following parameters, you can set them by instance creation. + * This action will override setting in PushPayload Optional. + * * apnsProduction If not present, the default is true. + * * timeToLive If not present, the default is 86400(s) (one day). + * + * Can be used directly. + */ +public class PushClient { + + private final NativeHttpClient _httpClient; + private String _baseUrl; + private String _pushPath; + private String _pushValidatePath; + + private JsonParser _jsonParser = new JsonParser(); + + // If not present, true by default. + private boolean _apnsProduction = true; + + // If not present, the default value is 86400(s) (one day) + private long _timeToLive = 60 * 60 * 24; + + private boolean _globalSettingEnabled = false; + + /** + * Create a Push Client. + * + * @param masterSecret API access secret of the appKey. + * @param appKey The KEY of one application on JPush. + */ + public PushClient(String masterSecret, String appKey) { + this(masterSecret, appKey, IHttpClient.DEFAULT_MAX_RETRY_TIMES); + } + + public PushClient(String masterSecret, String appKey, int maxRetryTimes) { + this(masterSecret, appKey, maxRetryTimes, null); + } + + /** + * Create a Push Client with max retry times. + * + * @param masterSecret API access secret of the appKey. + * @param appKey The KEY of one application on JPush. + * @param maxRetryTimes max retry times + */ + public PushClient(String masterSecret, String appKey, int maxRetryTimes, HttpProxy proxy) { + this(masterSecret, appKey, maxRetryTimes, proxy, ClientConfig.getInstance()); + } + + public PushClient(String masterSecret, String appKey, int maxRetryTimes, HttpProxy proxy, ClientConfig conf) { + ServiceHelper.checkBasic(appKey, masterSecret); + + this._baseUrl = (String) conf.get(ClientConfig.PUSH_HOST_NAME); + this._pushPath = (String) conf.get(ClientConfig.PUSH_PATH); + this._pushValidatePath = (String) conf.get(ClientConfig.PUSH_VALIDATE_PATH); + + String authCode = ServiceHelper.getBasicAuthorization(appKey, masterSecret); + this._httpClient = new NativeHttpClient(authCode, maxRetryTimes, proxy); + + } + + /** + * Create a Push Client with global settings. + * + * If you want different settings from default globally, this constructor is what you needed. + * + * @param masterSecret API access secret of the appKey. + * @param appKey The KEY of one application on JPush. + * @param apnsProduction Global APNs environment setting. It will override PushPayload Options. + * @param timeToLive Global time_to_live setting. It will override PushPayload Options. + */ + public PushClient(String masterSecret, String appKey, boolean apnsProduction, long timeToLive) { + this(masterSecret, appKey); + + this._apnsProduction = apnsProduction; + this._timeToLive = timeToLive; + this._globalSettingEnabled = true; + } + + public void setDefaults(boolean apnsProduction, long timeToLive) { + this._apnsProduction = apnsProduction; + this._timeToLive = timeToLive; + this._globalSettingEnabled = true; + } + + public void setBaseUrl(String baseUrl) { + this._baseUrl = baseUrl; + } + + public PushResult sendPush(PushPayload pushPayload) throws APIConnectionException, APIRequestException { + Preconditions.checkArgument(! (null == pushPayload), "pushPayload should not be null"); + + if (_globalSettingEnabled) { + pushPayload.resetOptionsTimeToLive(_timeToLive); + pushPayload.resetOptionsApnsProduction(_apnsProduction); + } + + ResponseWrapper response = _httpClient.sendPost(_baseUrl + _pushPath, pushPayload.toString()); + + return BaseResult.fromResponse(response, PushResult.class); + } + + public PushResult sendPushValidate(PushPayload pushPayload) throws APIConnectionException, APIRequestException { + Preconditions.checkArgument(! (null == pushPayload), "pushPayload should not be null"); + + if (_globalSettingEnabled) { + pushPayload.resetOptionsTimeToLive(_timeToLive); + pushPayload.resetOptionsApnsProduction(_apnsProduction); + } + + ResponseWrapper response = _httpClient.sendPost(_baseUrl + _pushValidatePath, pushPayload.toString()); + + return BaseResult.fromResponse(response, PushResult.class); + } + + public PushResult sendPush(String payloadString) throws APIConnectionException, APIRequestException { + Preconditions.checkArgument(StringUtils.isNotEmpty(payloadString), "pushPayload should not be empty"); + + try { + _jsonParser.parse(payloadString); + } catch (JsonParseException e) { + Preconditions.checkArgument(false, "payloadString should be a valid JSON string."); + } + + ResponseWrapper response = _httpClient.sendPost(_baseUrl + _pushPath, payloadString); + + return BaseResult.fromResponse(response, PushResult.class); + } + + public PushResult sendPushValidate(String payloadString) throws APIConnectionException, APIRequestException { + Preconditions.checkArgument(StringUtils.isNotEmpty(payloadString), "pushPayload should not be empty"); + + try { + _jsonParser.parse(payloadString); + } catch (JsonParseException e) { + Preconditions.checkArgument(false, "payloadString should be a valid JSON string."); + } + + ResponseWrapper response = _httpClient.sendPost(_baseUrl + _pushValidatePath, payloadString); + + return BaseResult.fromResponse(response, PushResult.class); + } + + +} + + diff --git a/.svn/pristine/38/3830e1f00b857af43b1356fb9ea9e29c3d537559.svn-base b/.svn/pristine/38/3830e1f00b857af43b1356fb9ea9e29c3d537559.svn-base new file mode 100644 index 0000000..279d394 --- /dev/null +++ b/.svn/pristine/38/3830e1f00b857af43b1356fb9ea9e29c3d537559.svn-base @@ -0,0 +1,191 @@ +package com.ifish.jpush.examples; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.ifish.jpush.JPushClient; +import com.ifish.jpush.common.TimeUnit; +import com.ifish.jpush.common.Week; +import com.ifish.jpush.common.resp.APIConnectionException; +import com.ifish.jpush.common.resp.APIRequestException; +import com.ifish.jpush.push.model.PushPayload; +import com.ifish.jpush.schedule.ScheduleListResult; +import com.ifish.jpush.schedule.ScheduleResult; +import com.ifish.jpush.schedule.model.SchedulePayload; +import com.ifish.jpush.schedule.model.TriggerPayload; + +public class ScheduleExample { + + protected static final Logger LOG = LoggerFactory.getLogger(ScheduleExample.class); + + private static final String appKey ="e5c0d34f58732cf09b2d4d74"; + private static final String masterSecret = "4cdda6d3c8b029941dbc5cb3"; + + public static void main(String[] args) { + +// testDeleteSchedule(); + testGetScheduleList(); +// testUpdateSchedule(); + testGetSchedule(); + } + + public static void testCreateSingleSchedule() { + JPushClient jpushClient = new JPushClient(masterSecret, appKey); + String name = "test_schedule_example"; + String time = "2016-07-30 12:30:25"; + PushPayload push = PushPayload.alertAll("test schedule example."); + try { + ScheduleResult result = jpushClient.createSingleSchedule(name, time, push); + LOG.info("schedule result is " + result); + } catch (APIConnectionException e) { + LOG.error("Connection error. Should retry later. ", e); + } catch (APIRequestException e) { + LOG.error("Error response from JPush server. Should review and fix it. ", e); + LOG.info("HTTP Status: " + e.getStatus()); + LOG.info("Error Code: " + e.getErrorCode()); + LOG.info("Error Message: " + e.getErrorMessage()); + } + } + + public static void testCreateDailySchedule() { + JPushClient jPushClient = new JPushClient(masterSecret, appKey); + String name = "test_daily_schedule"; + String start = "2015-08-06 12:16:13"; + String end = "2115-08-06 12:16:13"; + String time = "14:00:00"; + PushPayload push = PushPayload.alertAll("test daily example."); + try { + ScheduleResult result = jPushClient.createDailySchedule(name, start, end, time, push); + LOG.info("schedule result is " + result); + } catch (APIConnectionException e) { + LOG.error("Connection error. Should retry later. ", e); + } catch (APIRequestException e) { + LOG.error("Error response from JPush server. Should review and fix it. ", e); + LOG.info("HTTP Status: " + e.getStatus()); + LOG.info("Error Code: " + e.getErrorCode()); + LOG.info("Error Message: " + e.getErrorMessage()); + } + } + + public static void testCreateWeeklySchedule() { + JPushClient jPushClient = new JPushClient(masterSecret, appKey); + String name = "test_weekly_schedule"; + String start = "2015-08-06 12:16:13"; + String end = "2115-08-06 12:16:13"; + String time = "14:00:00"; + Week[] days = {Week.MON, Week.FRI}; + PushPayload push = PushPayload.alertAll("test weekly example."); + try { + ScheduleResult result = jPushClient.createWeeklySchedule(name, start, end, time, days, push); + LOG.info("schedule result is " + result); + } catch (APIConnectionException e) { + LOG.error("Connection error. Should retry later. ", e); + } catch (APIRequestException e) { + LOG.error("Error response from JPush server. Should review and fix it. ", e); + LOG.info("HTTP Status: " + e.getStatus()); + LOG.info("Error Code: " + e.getErrorCode()); + LOG.info("Error Message: " + e.getErrorMessage()); + } + } + + public static void testCreateMonthlySchedule() { + JPushClient jPushClient = new JPushClient(masterSecret, appKey); + String name = "test_monthly_schedule"; + String start = "2015-08-06 12:16:13"; + String end = "2115-08-06 12:16:13"; + String time = "14:00:00"; + String[] points = {"01", "02"}; + PushPayload push = PushPayload.alertAll("test monthly example."); + try { + ScheduleResult result = jPushClient.createMonthlySchedule(name, start, end, time, points, push); + LOG.info("schedule result is " + result); + } catch (APIConnectionException e) { + LOG.error("Connection error. Should retry later.", e); + } catch (APIRequestException e) { + LOG.error("Error response from JPush server. Should review and fix it. ", e); + LOG.info("HTTP Status: " + e.getStatus()); + LOG.info("Error Code: " + e.getErrorCode()); + LOG.info("Error Message: " + e.getErrorMessage()); + } + } + + public static void testDeleteSchedule() { + String scheduleId = "95bbd066-3a88-11e5-8e62-0021f652c102"; + JPushClient jpushClient = new JPushClient(masterSecret, appKey); + + try { + jpushClient.deleteSchedule(scheduleId); + } catch (APIConnectionException e) { + LOG.error("Connection error. Should retry later. ", e); + } catch (APIRequestException e) { + LOG.error("Error response from JPush server. Should review and fix it. ", e); + LOG.info("HTTP Status: " + e.getStatus()); + LOG.info("Error Code: " + e.getErrorCode()); + LOG.info("Error Message: " + e.getErrorMessage()); + } + } + + public static void testGetScheduleList() { + int page = 1; + JPushClient jpushClient = new JPushClient(masterSecret, appKey); + + try { + ScheduleListResult list = jpushClient.getScheduleList(page); + LOG.info("total " + list.getTotal_count()); + for(ScheduleResult s : list.getSchedules()) { + LOG.info(s.toString()); + } + } catch (APIConnectionException e) { + LOG.error("Connection error. Should retry later. ", e); + } catch (APIRequestException e) { + LOG.error("Error response from JPush server. Should review and fix it. ", e); + LOG.info("HTTP Status: " + e.getStatus()); + LOG.info("Error Code: " + e.getErrorCode()); + LOG.info("Error Message: " + e.getErrorMessage()); + } + } + + public static void testUpdateSchedule() { + String scheduleId = "95bbd066-3a88-11e5-8e62-0021f652c102"; + JPushClient jpushClient = new JPushClient(masterSecret, appKey); + String[] points = {Week.MON.name(), Week.FRI.name()}; + TriggerPayload trigger = TriggerPayload.newBuilder() + .setPeriodTime("2015-08-01 12:10:00", "2015-08-30 12:12:12", "15:00:00") + .setTimeFrequency(TimeUnit.WEEK, 2, points) + .buildPeriodical(); + SchedulePayload payload = SchedulePayload.newBuilder() + .setName("test_update_schedule") + .setEnabled(false) + .setTrigger(trigger) + .build(); + try { + jpushClient.updateSchedule(scheduleId, payload); + } catch (APIConnectionException e) { + LOG.error("Connection error. Should retry later. ", e); + } catch (APIRequestException e) { + LOG.error("Error response from JPush server. Should review and fix it. ", e); + LOG.info("HTTP Status: " + e.getStatus()); + LOG.info("Error Code: " + e.getErrorCode()); + LOG.info("Error Message: " + e.getErrorMessage()); + } + } + + public static void testGetSchedule() { + String scheduleId = "95bbd066-3a88-11e5-8e62-0021f652c102"; + JPushClient jpushClient = new JPushClient(masterSecret, appKey); + + try { + ScheduleResult result = jpushClient.getSchedule(scheduleId); + LOG.info("schedule " + result); + } catch (APIConnectionException e) { + LOG.error("Connection error. Should retry later. ", e); + } catch (APIRequestException e) { + LOG.error("Error response from JPush server. Should review and fix it. ", e); + LOG.info("HTTP Status: " + e.getStatus()); + LOG.info("Error Code: " + e.getErrorCode()); + LOG.info("Error Message: " + e.getErrorMessage()); + } + } + + +} diff --git a/.svn/pristine/40/40a8f072235ced339af981f29f99af2177a35b58.svn-base b/.svn/pristine/40/40a8f072235ced339af981f29f99af2177a35b58.svn-base new file mode 100644 index 0000000..17f8d92 --- /dev/null +++ b/.svn/pristine/40/40a8f072235ced339af981f29f99af2177a35b58.svn-base @@ -0,0 +1,12 @@ +#appKey +jpush.android.appKey=d970d5e193cb2a0bbe41653c +#secret +jpush.android.secret=60162c8cf195ce9f4dc76629 +#production +jpush.android.productionMode=true +#appKey +jpush.ios.appKey=d147124018074eb970474e48 +#secret +jpush.ios.secret=a7d41825e75082b13675c326 +#production +jpush.ios.productionMode=true diff --git a/.svn/pristine/41/41dc938ac9888d7fb2ef95cd6e1fd25d0bf5d174.svn-base b/.svn/pristine/41/41dc938ac9888d7fb2ef95cd6e1fd25d0bf5d174.svn-base new file mode 100644 index 0000000..31795d9 --- /dev/null +++ b/.svn/pristine/41/41dc938ac9888d7fb2ef95cd6e1fd25d0bf5d174.svn-base @@ -0,0 +1,97 @@ +package com.ifish.jpush.schedule; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.ifish.jpush.common.ClientConfig; +import com.ifish.jpush.common.ServiceHelper; +import com.ifish.jpush.common.connection.HttpProxy; +import com.ifish.jpush.common.connection.IHttpClient; +import com.ifish.jpush.common.connection.NativeHttpClient; +import com.ifish.jpush.common.resp.APIConnectionException; +import com.ifish.jpush.common.resp.APIRequestException; +import com.ifish.jpush.common.resp.ResponseWrapper; +import com.ifish.jpush.schedule.model.SchedulePayload; +import com.ifish.jpush.utils.Preconditions; +import com.ifish.jpush.utils.StringUtils; + +public class ScheduleClient { + + private static final Logger LOG = LoggerFactory.getLogger(ScheduleClient.class); + private final NativeHttpClient _httpClient; + + private String hostName; + private String schedulePath; + + public ScheduleClient(String masterSecret, String appkey) { + this(masterSecret, appkey, IHttpClient.DEFAULT_MAX_RETRY_TIMES, null, ClientConfig.getInstance()); + } + + public ScheduleClient(String masterSecret, String appKey, int maxRetryTimes) { + this(masterSecret, appKey, maxRetryTimes, null, ClientConfig.getInstance()); + } + + public ScheduleClient(String masterSecret, String appKey, int maxRetryTimes, HttpProxy proxy) { + this(masterSecret, appKey, maxRetryTimes, proxy, ClientConfig.getInstance()); + } + + /** + * Create a Schedule Client with custom configuration. + * @param masterSecret API access secret of the appKey. + * @param appKey The KEY of one application on JPush. + * @param maxRetryTimes Max retry times + * @param proxy The proxy, if there is no proxy, should be null. + * @param conf The client configuration. Can use ClientConfig.getInstance() as default. + */ + public ScheduleClient(String masterSecret, String appKey, int maxRetryTimes, HttpProxy proxy, ClientConfig conf) { + ServiceHelper.checkBasic(appKey, masterSecret); + hostName = (String) conf.get(ClientConfig.SCHEDULE_HOST_NAME); + schedulePath = (String) conf.get(ClientConfig.SCHEDULE_PATH); + + String authCode = ServiceHelper.getBasicAuthorization(appKey, masterSecret); + this._httpClient = new NativeHttpClient(authCode, maxRetryTimes, proxy); + } + + public ScheduleResult createSchedule(SchedulePayload payload) throws APIConnectionException, APIRequestException { + + Preconditions.checkArgument(null != payload, "payload should not be null"); + + ResponseWrapper response = _httpClient.sendPost(hostName + schedulePath, payload.toString()); + return ScheduleResult.fromResponse(response, ScheduleResult.class); + } + + public ScheduleListResult getScheduleList(int page) throws APIConnectionException, APIRequestException{ + + Preconditions.checkArgument(page > 0, "page should more than 0."); + + ResponseWrapper response = _httpClient.sendGet(hostName + schedulePath + "?page=" + page); + return ScheduleListResult.fromResponse(response, ScheduleListResult.class); + } + + public ScheduleResult getSchedule(String scheduleId) throws APIConnectionException, APIRequestException{ + + Preconditions.checkArgument(StringUtils.isNotEmpty(scheduleId), "scheduleId should not be empty"); + + ResponseWrapper response = _httpClient.sendGet(hostName + schedulePath + "/" + scheduleId); + return ScheduleResult.fromResponse(response, ScheduleResult.class); + } + + public ScheduleResult updateSchedule(String scheduleId, SchedulePayload payload) throws APIConnectionException, APIRequestException{ + + Preconditions.checkArgument(StringUtils.isNotEmpty(scheduleId), "scheduleId should not be empty"); + Preconditions.checkArgument(null != payload, "payload should not be null"); + + ResponseWrapper response = _httpClient.sendPut(hostName + schedulePath + "/" + scheduleId, + payload.toString()); + return ScheduleResult.fromResponse(response, ScheduleResult.class); + } + + public void deleteSchedule(String scheduleId) throws APIConnectionException, APIRequestException{ + + Preconditions.checkArgument(StringUtils.isNotEmpty(scheduleId), "scheduleId should not be empty"); + + _httpClient.sendDelete(hostName + schedulePath + "/" + scheduleId); + } + + +} diff --git a/.svn/pristine/41/41dfc0a6c92707948578891c51d98c6443be63cc.svn-base b/.svn/pristine/41/41dfc0a6c92707948578891c51d98c6443be63cc.svn-base new file mode 100644 index 0000000..05bd71b --- /dev/null +++ b/.svn/pristine/41/41dfc0a6c92707948578891c51d98c6443be63cc.svn-base @@ -0,0 +1 @@ +Window \ No newline at end of file diff --git a/.svn/pristine/46/466e587f383a9afff913479cecbe281c641c3bf2.svn-base b/.svn/pristine/46/466e587f383a9afff913479cecbe281c641c3bf2.svn-base new file mode 100644 index 0000000..7c77271 --- /dev/null +++ b/.svn/pristine/46/466e587f383a9afff913479cecbe281c641c3bf2.svn-base @@ -0,0 +1,131 @@ +package com.ifish.jpush.push.model.notification; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import com.ifish.jpush.push.model.PushModel; +import com.ifish.jpush.utils.StringUtils; + +public class IosAlert implements PushModel { + + private final String title; + private final String body; + private final String title_loc_key; + private final String[] title_loc_args; + private final String action_loc_key; + private final String loc_key; + private final String[] loc_args; + private final String launch_image; + + private IosAlert(String title, String body, String title_loc_key, String[] title_loc_args, + String action_loc_key, String loc_key, String[] loc_args, String launch_image) { + this.title = title; + this.body = body; + this.title_loc_key = title_loc_key; + this.title_loc_args = title_loc_args; + this.action_loc_key = action_loc_key; + this.loc_key = loc_key; + this.loc_args = loc_args; + this.launch_image = launch_image; + } + + public static Builder newBuilder() { + return new Builder(); + } + + @Override + public JsonElement toJSON() { + JsonObject json = new JsonObject(); + + if( StringUtils.isNotEmpty(title) ) { + json.addProperty("title", title); + } + + if( StringUtils.isNotEmpty(body) ) { + json.addProperty("body", body); + } + + if( StringUtils.isNotEmpty(title_loc_key) ) { + json.addProperty("title-loc-key", title_loc_key); + if( null != title_loc_args && title_loc_args.length > 0 ) { + JsonArray args = new JsonArray(); + for(int i = 0; i < title_loc_args.length; i++) { + args.add(new JsonPrimitive(title_loc_args[i])); + } + json.add("title-loc-args", args); + } + } + + if( StringUtils.isNotEmpty(action_loc_key) ) { + json.addProperty("action-loc-key", action_loc_key); + } + + if( StringUtils.isNotEmpty(loc_key) ) { + json.addProperty("loc-key", loc_key); + if( null != loc_args && loc_args.length > 0 ) { + JsonArray args = new JsonArray(); + for(int i = 0; i < loc_args.length; i++) { + args.add(new JsonPrimitive(loc_args[i])); + } + json.add("loc-args", args); + } + } + + if( StringUtils.isNotEmpty(launch_image) ) { + json.addProperty("launch-image", launch_image); + } + + return json; + } + + @Override + public String toString() { + return gson.toJson(toJSON()); + } + + public static class Builder { + private String title; + private String body; + private String title_loc_key; + private String[] title_loc_args; + private String action_loc_key; + private String loc_key; + private String[] loc_args; + private String launch_image; + + public Builder setTitleAndBody(String title, String body){ + this.title = title; + this.body = body; + return this; + } + + public Builder setTitleLoc(String title_loc_key, String... title_loc_args) { + this.title_loc_key = title_loc_key; + this.title_loc_args = title_loc_args; + return this; + } + + public Builder setActionLocKey(String action_loc_key) { + this.action_loc_key = action_loc_key; + return this; + } + + public Builder setLoc(String loc_key, String... loc_args) { + this.loc_key = loc_key; + this.loc_args = loc_args; + return this; + } + + public Builder setLaunchImage(String launch_image) { + this.launch_image = launch_image; + return this; + } + + public IosAlert build() { + return new IosAlert(title, body, title_loc_key, title_loc_args, action_loc_key, + loc_key, loc_args, launch_image); + } + } + +} diff --git a/.svn/pristine/48/483cd9fda35fccd646a47bac34d7e7febd072b38.svn-base b/.svn/pristine/48/483cd9fda35fccd646a47bac34d7e7febd072b38.svn-base new file mode 100644 index 0000000..0665370 --- /dev/null +++ b/.svn/pristine/48/483cd9fda35fccd646a47bac34d7e7febd072b38.svn-base @@ -0,0 +1,120 @@ +package com.ifish.jpush.utils; + +import java.io.CharArrayWriter; +import java.io.IOException; + +public class Base64 { + static final char[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" + .toCharArray(); + + public static char[] encode(byte[] content) { + CharArrayWriter cw = new CharArrayWriter(4 * content.length / 3); + + int idx = 0; + + int x = 0; + + for (int i = 0; i < content.length; ++i) { + if (idx == 0) + x = (content[i] & 0xFF) << 16; + else if (idx == 1) + x |= (content[i] & 0xFF) << 8; + else { + x |= content[i] & 0xFF; + } + + if (++idx == 3) { + cw.write(alphabet[(x >> 18)]); + cw.write(alphabet[(x >> 12 & 0x3F)]); + cw.write(alphabet[(x >> 6 & 0x3F)]); + cw.write(alphabet[(x & 0x3F)]); + + idx = 0; + } + } + + if (idx == 1) { + cw.write(alphabet[(x >> 18)]); + cw.write(alphabet[(x >> 12 & 0x3F)]); + cw.write(61); + cw.write(61); + } + + if (idx == 2) { + cw.write(alphabet[(x >> 18)]); + cw.write(alphabet[(x >> 12 & 0x3F)]); + cw.write(alphabet[(x >> 6 & 0x3F)]); + cw.write(61); + } + + return cw.toCharArray(); + } + + public static byte[] decode(char[] message) throws IOException { + byte[] buff = new byte[4]; + byte[] dest = new byte[message.length]; + + int bpos = 0; + int destpos = 0; + + for (int i = 0; i < message.length; ++i) { + int c = message[i]; + + if ((c != 10) && (c != 13) && (c != 32)) { + if (c == 9) + continue; + + if ((c >= 65) && (c <= 90)) { + buff[(bpos++)] = (byte) (c - 65); + } else if ((c >= 97) && (c <= 122)) { + buff[(bpos++)] = (byte) (c - 97 + 26); + } else if ((c >= 48) && (c <= 57)) { + buff[(bpos++)] = (byte) (c - 48 + 52); + } else if (c == 43) { + buff[(bpos++)] = 62; + } else if (c == 47) { + buff[(bpos++)] = 63; + } else if (c == 61) { + buff[(bpos++)] = 64; + } else { + throw new IOException("Illegal char in base64 code."); + } + + if (bpos == 4) { + bpos = 0; + + if (buff[0] == 64) + break; + + if (buff[1] == 64) + throw new IOException("Unexpected '=' in base64 code."); + + int v; + if (buff[2] == 64) { + v = (buff[0] & 0x3F) << 6 | buff[1] & 0x3F; + dest[(destpos++)] = (byte) (v >> 4); + break; + } + if (buff[3] == 64) { + v = (buff[0] & 0x3F) << 12 | (buff[1] & 0x3F) << 6 + | buff[2] & 0x3F; + dest[(destpos++)] = (byte) (v >> 10); + dest[(destpos++)] = (byte) (v >> 2); + break; + } + + v = (buff[0] & 0x3F) << 18 | (buff[1] & 0x3F) << 12 + | (buff[2] & 0x3F) << 6 | buff[3] & 0x3F; + dest[(destpos++)] = (byte) (v >> 16); + dest[(destpos++)] = (byte) (v >> 8); + dest[(destpos++)] = (byte) v; + } + } + } + + byte[] res = new byte[destpos]; + System.arraycopy(dest, 0, res, 0, destpos); + + return res; + } +} \ No newline at end of file diff --git a/.svn/pristine/48/48426d315a1f1ab0262e751165d06e6e7c1a2a6f.svn-base b/.svn/pristine/48/48426d315a1f1ab0262e751165d06e6e7c1a2a6f.svn-base new file mode 100644 index 0000000..9e07c1f --- /dev/null +++ b/.svn/pristine/48/48426d315a1f1ab0262e751165d06e6e7c1a2a6f.svn-base @@ -0,0 +1,14 @@ +package com.ifish.jpush.device; + +import java.util.ArrayList; +import java.util.List; + +import com.google.gson.annotations.Expose; +import com.ifish.jpush.common.resp.BaseResult; + +public class AliasDeviceListResult extends BaseResult { + + @Expose public List registration_ids = new ArrayList(); + +} + diff --git a/.svn/pristine/4e/4e5f2975a003c3be4acb356aaa46622e1d4aa624.svn-base b/.svn/pristine/4e/4e5f2975a003c3be4acb356aaa46622e1d4aa624.svn-base new file mode 100644 index 0000000..ea18499 --- /dev/null +++ b/.svn/pristine/4e/4e5f2975a003c3be4acb356aaa46622e1d4aa624.svn-base @@ -0,0 +1,199 @@ +package com.ifish.jpush.push.model.notification; + +import java.util.HashMap; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import com.ifish.jpush.push.model.PushModel; +import com.ifish.jpush.utils.Preconditions; + +public abstract class PlatformNotification implements PushModel { + public static final String ALERT = "alert"; + private static final String EXTRAS = "extras"; + + protected static final Logger LOG = LoggerFactory.getLogger(PlatformNotification.class); + + private Object alert; + private final Map extras; + private final Map numberExtras; + private final Map booleanExtras; + private final Map jsonExtras; + + public PlatformNotification(Object alert, Map extras, + Map numberExtras, + Map booleanExtras, + Map jsonExtras) { + this.alert = alert; + this.extras = extras; + this.numberExtras = numberExtras; + this.booleanExtras = booleanExtras; + this.jsonExtras = jsonExtras; + } + + @Override + public JsonElement toJSON() { + JsonObject json = new JsonObject(); + + if (null != alert) { + if ( alert instanceof JsonObject) { + json.add(ALERT, (JsonObject) alert); + } else if (alert instanceof IosAlert) { + json.add(ALERT, ((IosAlert) alert).toJSON()); + } else { + json.add(ALERT, new JsonPrimitive(alert.toString())); + } + } + + JsonObject extrasObject = null; + if (null != extras || null != numberExtras || null != booleanExtras || null != jsonExtras) { + extrasObject = new JsonObject(); + } + + if (null != extras) { + String value = null; + for (String key : extras.keySet()) { + value = extras.get(key); + if (null != value) { + extrasObject.add(key, new JsonPrimitive(value)); + } + } + } + if (null != numberExtras) { + Number value = null; + for (String key : numberExtras.keySet()) { + value = numberExtras.get(key); + if (null != value) { + extrasObject.add(key, new JsonPrimitive(value)); + } + } + } + if (null != booleanExtras) { + Boolean value = null; + for (String key : booleanExtras.keySet()) { + value = booleanExtras.get(key); + if (null != value) { + extrasObject.add(key, new JsonPrimitive(value)); + } + } + } + if (null != jsonExtras) { + JsonObject value = null; + for (String key : jsonExtras.keySet()) { + value = jsonExtras.get(key); + if (null != value) { + extrasObject.add(key, value); + } + } + } + + if (null != extras || null != numberExtras || null != booleanExtras || null != jsonExtras) { + json.add(EXTRAS, extrasObject); + } + + return json; + } + + protected Object getAlert() { + return this.alert; + } + + protected void setAlert(Object alert) { + this.alert = alert; + } + + protected abstract String getPlatform(); + + protected abstract static class Builder> { + private B theBuilder; + + protected Object alert; + protected Map extrasBuilder; + protected Map numberExtrasBuilder; + protected Map booleanExtrasBuilder; + protected Map jsonExtrasBuilder; + + public Builder () { + theBuilder = getThis(); + } + + protected abstract B getThis(); + + public abstract B setAlert(Object alert); + + public B addExtra(String key, String value) { + Preconditions.checkArgument(! (null == key), "Key should not be null."); + if (null == value) { + LOG.debug("Extra value is null, throw away it."); + return theBuilder; + } + if (null == extrasBuilder) { + extrasBuilder = new HashMap(); + } + extrasBuilder.put(key, value); + return theBuilder; + } + + public B addExtras(Map extras) { + if (null == extras) { + LOG.warn("Null extras param. Throw away it."); + return theBuilder; + } + + if (null == extrasBuilder) { + extrasBuilder = new HashMap(); + } + for (String key : extras.keySet()) { + extrasBuilder.put(key, extras.get(key)); + } + return theBuilder; + } + + public B addExtra(String key, Number value) { + Preconditions.checkArgument(! (null == key), "Key should not be null."); + if (null == value) { + LOG.debug("Extra value is null, throw away it."); + return theBuilder; + } + if (null == numberExtrasBuilder) { + numberExtrasBuilder = new HashMap(); + } + numberExtrasBuilder.put(key, value); + return theBuilder; + } + + public B addExtra(String key, Boolean value) { + Preconditions.checkArgument(! (null == key), "Key should not be null."); + if (null == value) { + LOG.debug("Extra value is null, throw away it."); + return theBuilder; + } + if (null == booleanExtrasBuilder) { + booleanExtrasBuilder = new HashMap(); + } + booleanExtrasBuilder.put(key, value); + return theBuilder; + } + + public B addExtra(String key, JsonObject value) { + Preconditions.checkArgument(! (null == key), "Key should not be null."); + if (null == value) { + LOG.debug("Extra value is null, throw away it."); + return theBuilder; + } + if (null == jsonExtrasBuilder) { + jsonExtrasBuilder = new HashMap(); + } + jsonExtrasBuilder.put(key, value); + return theBuilder; + } + + public abstract T build(); + } + + +} diff --git a/.svn/pristine/4f/4fc59ae5498872a9417286afbe51c5b394467d6a.svn-base b/.svn/pristine/4f/4fc59ae5498872a9417286afbe51c5b394467d6a.svn-base new file mode 100644 index 0000000..e78d401 --- /dev/null +++ b/.svn/pristine/4f/4fc59ae5498872a9417286afbe51c5b394467d6a.svn-base @@ -0,0 +1,12 @@ +package com.ifish.jpush.push; + +import com.google.gson.annotations.Expose; +import com.ifish.jpush.common.resp.BaseResult; + +public class PushResult extends BaseResult { + + @Expose public long msg_id; + @Expose public int sendno; + +} + diff --git a/.svn/pristine/54/54ff87afb40e87799ca3f3e029c168da47ee873f.svn-base b/.svn/pristine/54/54ff87afb40e87799ca3f3e029c168da47ee873f.svn-base new file mode 100644 index 0000000..38f1146 --- /dev/null +++ b/.svn/pristine/54/54ff87afb40e87799ca3f3e029c168da47ee873f.svn-base @@ -0,0 +1,184 @@ + + 4.0.0 + quartzPro + quartzPro + war + 0.0.1-SNAPSHOT + quartzPro + http://mvnrepository.com + + + + + org.quartz-scheduler + quartz + 2.2.1 + + + + net.sf.json-lib + json-lib + 2.4 + jdk15 + + + + org.apache.httpcomponents + httpclient + 4.3.5 + + + + javax.servlet + javax.servlet-api + 3.0.1 + + + + org.springframework + spring-core + 4.1.6.RELEASE + + + + org.springframework + spring-context + 4.1.6.RELEASE + + + + org.springframework + spring-context-support + 4.1.6.RELEASE + + + + org.aspectj + aspectjweaver + 1.8.5 + + + + org.springframework + spring-aspects + 4.1.6.RELEASE + + + + org.springframework + spring-orm + 4.1.6.RELEASE + + + + org.springframework + spring-beans + 4.1.6.RELEASE + + + + org.springframework + spring-aop + 4.1.6.RELEASE + + + + org.springframework + spring-webmvc + 4.1.6.RELEASE + + + + c3p0 + c3p0 + 0.9.1.2 + + + + org.slf4j + slf4j-api + 1.7.12 + + + + ch.qos.logback + logback-core + 1.1.2 + + + + ch.qos.logback + logback-classic + 1.1.2 + + + + org.hibernate + hibernate-core + 4.3.11.Final + + + + org.jboss.logging + jboss-logging-annotations + 2.0.1.Final + + + + org.json + json + 20090211 + + + + com.google.code.gson + gson + 2.3 + + + + + quartzPro + + + org.apache.maven.plugins + maven-war-plugin + 2.4 + + + + src/main/webapp + + + + + + org.apache.felix + maven-bundle-plugin + 2.5.4 + true + + + + + src/main/java + + **/*.hbm.xml + + + + src/main/resources + + **/*.xml + **/*.properties + + + + + + + UTF-8 + + + diff --git a/.svn/pristine/55/55e16a0d52a656cc039079d09a32292b34168237.svn-base b/.svn/pristine/55/55e16a0d52a656cc039079d09a32292b34168237.svn-base new file mode 100644 index 0000000..2560447 --- /dev/null +++ b/.svn/pristine/55/55e16a0d52a656cc039079d09a32292b34168237.svn-base @@ -0,0 +1,11 @@ +<%@ page language="java" pageEncoding="utf-8"%> + + + + 首页 + + + +

访问正常

+ + diff --git a/.svn/pristine/56/56b1e44d04f049747f2792ee3077e80d23bdb461.svn-base b/.svn/pristine/56/56b1e44d04f049747f2792ee3077e80d23bdb461.svn-base new file mode 100644 index 0000000..48dd452 --- /dev/null +++ b/.svn/pristine/56/56b1e44d04f049747f2792ee3077e80d23bdb461.svn-base @@ -0,0 +1,172 @@ +package com.ifish.job; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import net.sf.json.JSONArray; + +import org.springframework.beans.factory.annotation.Autowired; + +import com.ifish.enums.PhoneTypeEnum; +import com.ifish.jpush.JPushNotification; +import com.ifish.netease.NeteaseIM; +import com.ifish.util.IfishUtil; + +public class job{ + @Autowired + private NeteaseIM neteaseIM; + @Autowired + private JPushNotification jPushNotification; + @Autowired + private JPushNotification jPushNotification2; + + private Connection connection = null; + private Statement stmt = null; + private PreparedStatement prest = null; + + /** + * 查询需要推送的用户并且推送完修改为下一次提醒日期 + */ + public void pushRemind(){ + System.out.println(new Date()+"开始任务"); + try { + Class.forName("com.mysql.jdbc.Driver"); + connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/myfishdb?characterEncoding=UTF-8", "ifish", "ifish7pwd"); + stmt = connection.createStatement(); + prest = connection.prepareStatement("update tbl_tmp_push_remind set is_push=? where user_id=? and device_id=?"); + } catch (SQLException e) { + e.printStackTrace(); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + //结果集 + ResultSet result = null; + try { + //推送提醒数 + int rowCount = 0; + //按分页来获取数据 + int pageNo = 0; + //云信限制每次最多500条 + int pageSize = 500; + //查询总共需要推送的用户数 + String countSql = "select count(1) as countRow from tbl_tmp_push_remind where is_push='0'"; + result = stmt.executeQuery(countSql); + if(result.next()){ + rowCount=result.getInt("countRow"); + pageNo = (rowCount+pageSize-1)/pageSize; + } + System.out.println(pageNo); + for (int i = 0; i < pageNo; i++) { + result = stmt.executeQuery("select device_id,user_id,show_name,login_type from tbl_tmp_push_remind where is_push='0' limit 0,"+pageSize); + //推送的用户 + List androidUser = new ArrayList(); + List iosUser = new ArrayList(); + List ids = new ArrayList(); + //更新提醒过的用户 + while(result.next()){ + Integer deviceId= result.getInt("device_id"); + Integer userId = result.getInt("user_id"); + String loginType = result.getString("login_type"); + prest.setString(1, "1"); + prest.setInt(2, userId); + prest.setInt(3, deviceId); + prest.addBatch(); + //云信 + ids.add(userId.toString()); + //极光 + if(loginType.toLowerCase().equals(PhoneTypeEnum.android.getKey())){ + androidUser.add(userId.toString()); + } + else if(loginType.toLowerCase().equals(PhoneTypeEnum.ios.getKey())){ + iosUser.add(userId.toString()); + } + } + //发送云信消息 + if(ids.size()>0){ + neteaseIM.sendBatchMsg("ifish", JSONArray.fromObject(ids).toString(), "【换水提醒】您的水族箱需要换水啦~您可以在水箱设置中更改提醒设置"); + } + //极光推送 + Integer iosSize = iosUser.size(); + Integer androidSize = androidUser.size(); + if(iosSize>0){ + push(PhoneTypeEnum.ios,iosUser.toArray(new String[iosSize])); + } + if(androidSize>0){ + push(PhoneTypeEnum.android,androidUser.toArray(new String[androidSize])); + } + //批量提交 + prest.executeBatch(); + //云信一分钟访问不超过120次 + Thread.sleep(600); + } + } catch (Exception e) { + e.printStackTrace(); + } + finally{ + if(result!=null){ + try { + result.close(); + result = null; + } catch (SQLException e) { + e.printStackTrace(); + } + } + if(stmt!=null){ + try { + stmt.close(); + stmt = null; + } catch (SQLException e) { + e.printStackTrace(); + } + } + if(prest!=null){ + try { + prest.close(); + prest = null; + } catch (SQLException e) { + e.printStackTrace(); + } + } + if(connection!=null){ + try { + connection.close(); + connection = null; + } catch (SQLException e) { + e.printStackTrace(); + } + } + } + } + /** + * 推送提醒 + * @param type + * @param ids + */ + public void push(PhoneTypeEnum type,String[] ids){ + try { + Map map = new HashMap(); + map.put("timestamp", IfishUtil.format2(new Date())); + //推送android + if(type.equals(PhoneTypeEnum.android)){ + System.out.println(new Date()+"android推送"+ids.length+"个"); + jPushNotification.sendAndroidNotification(ids, "换水提醒", "您的水族箱需要换水啦~您可以在水箱设置中更改提醒设置", map); + } + //推送IOS + else if(type.equals(PhoneTypeEnum.ios)){ + System.out.println(new Date()+"ios推送"+ids.length+"个"); + jPushNotification2.sendIosNotification(ids, "换水提醒", "您的水族箱需要换水啦~您可以在水箱设置中更改提醒设置", map); + } + } catch (Exception e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/.svn/pristine/59/5988b94afe4ed141884be62d5486d3e32f439960.svn-base b/.svn/pristine/59/5988b94afe4ed141884be62d5486d3e32f439960.svn-base new file mode 100644 index 0000000..25d3f8d --- /dev/null +++ b/.svn/pristine/59/5988b94afe4ed141884be62d5486d3e32f439960.svn-base @@ -0,0 +1,87 @@ +package com.ifish.jpush.push.model.notification; + +import java.util.Map; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; + +public class AndroidNotification extends PlatformNotification { + public static final String NOTIFICATION_ANDROID = "android"; + + private static final String TITLE = "title"; + private static final String BUILDER_ID = "builder_id"; + + private final String title; + private final int builderId; + + private AndroidNotification(Object alert, String title, int builderId, + Map extras, + Map numberExtras, + Map booleanExtras, + Map jsonExtras) { + super(alert, extras, numberExtras, booleanExtras, jsonExtras); + + this.title = title; + this.builderId = builderId; + } + + public static Builder newBuilder() { + return new Builder(); + } + + public static AndroidNotification alert(String alert) { + return newBuilder().setAlert(alert).build(); + } + + + @Override + public String getPlatform() { + return NOTIFICATION_ANDROID; + } + + @Override + public JsonElement toJSON() { + JsonObject json = super.toJSON().getAsJsonObject(); + + if (builderId > 0) { + json.add(BUILDER_ID, new JsonPrimitive(this.builderId)); + } + if (null != title) { + json.add(TITLE, new JsonPrimitive(title)); + } + + return json; + } + + + public static class Builder extends PlatformNotification.Builder { + private String title; + private int builderId; + + protected Builder getThis() { + return this; + } + + public Builder setTitle(String title) { + this.title = title; + return this; + } + + public Builder setBuilderId(int builderId) { + this.builderId = builderId; + return this; + } + + public Builder setAlert(Object alert) { + this.alert = alert; + return this; + } + + + public AndroidNotification build() { + return new AndroidNotification(alert, title, builderId, + extrasBuilder, numberExtrasBuilder, booleanExtrasBuilder, jsonExtrasBuilder); + } + } +} diff --git a/.svn/pristine/5f/5f860c17a04c2d398f45ce4eadb02d17c2831d28.svn-base b/.svn/pristine/5f/5f860c17a04c2d398f45ce4eadb02d17c2831d28.svn-base new file mode 100644 index 0000000..9322d3e --- /dev/null +++ b/.svn/pristine/5f/5f860c17a04c2d398f45ce4eadb02d17c2831d28.svn-base @@ -0,0 +1,182 @@ +package com.ifish.job; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import net.sf.json.JSONArray; + +import org.springframework.beans.factory.annotation.Autowired; + +import com.ifish.enums.PhoneTypeEnum; +import com.ifish.jpush.JPushNotification; +import com.ifish.netease.NeteaseIM; +import com.ifish.util.IfishUtil; + +public class job{ + @Autowired + private NeteaseIM neteaseIM; + @Autowired + private JPushNotification jPushNotification; + @Autowired + private JPushNotification jPushNotification2; + + private Connection connection = null; + private Statement stmt = null; + private PreparedStatement prest = null; + + /** + * 查询需要推送的用户并且推送完修改为下一次提醒日期 + */ + public void pushRemind(){ + System.out.println(new Date()+"开始任务"); + try { + Class.forName("com.mysql.jdbc.Driver"); + connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/myfishdb?characterEncoding=UTF-8", "ifish", "ifish7pwd"); + stmt = connection.createStatement(); + prest = connection.prepareStatement("update tbl_tmp_push_remind set is_push=? where user_id=? and device_id=?"); + } catch (SQLException e) { + e.printStackTrace(); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + //结果集 + ResultSet result = null; + try { + //推送提醒数 + int rowCount = 0; + //按分页来获取数据 + int pageNo = 0; + //云信限制每次最多500条 + int pageSize = 500; + //查询总共需要推送的用户数 + String countSql = "select count(1) as countRow from tbl_tmp_push_remind where is_push='0'"; + result = stmt.executeQuery(countSql); + if(result.next()){ + rowCount=result.getInt("countRow"); + pageNo = (rowCount+pageSize-1)/pageSize; + } + System.out.println(pageNo); + for (int i = 0; i < pageNo; i++) { + result = stmt.executeQuery("select device_id,user_id,show_name,login_type from tbl_tmp_push_remind where is_push='0' limit 0,"+pageSize); + //推送的用户 + List androidUser = new ArrayList(); + List iosUser = new ArrayList(); + List ids = new ArrayList(); + //是否云信 + boolean bln = true; + //更新提醒过的用户 + while(result.next()){ + Integer deviceId= result.getInt("device_id"); + Integer userId = result.getInt("user_id"); + String loginType = result.getString("login_type"); + prest.setString(1, "1"); + prest.setInt(2, userId); + prest.setInt(3, deviceId); + prest.addBatch(); + //云信 + if(bln){ + ids.add(userId.toString()); + } + else{ + //极光推送 + if(loginType.toLowerCase().equals(PhoneTypeEnum.android.getKey())){ + androidUser.add(userId.toString()); + } + else if(loginType.toLowerCase().equals(PhoneTypeEnum.ios.getKey())){ + iosUser.add(userId.toString()); + } + } + } + //云信 + if(bln){ + if(ids.size()>0){ + neteaseIM.sendBatchMsg("ifish", JSONArray.fromObject(ids).toString(), "您的水族箱需要换水啦~您可以在水箱设置中更改提醒设置"); + } + } + else{ + //极光推送 + Integer iosSize = iosUser.size(); + Integer androidSize = androidUser.size(); + if(iosSize>0){ + push(PhoneTypeEnum.ios,iosUser.toArray(new String[iosSize])); + } + if(androidSize>0){ + push(PhoneTypeEnum.android,androidUser.toArray(new String[androidSize])); + } + } + //批量提交 + prest.executeBatch(); + //云信一分钟访问不超过120次 + Thread.sleep(600); + } + } catch (Exception e) { + e.printStackTrace(); + } + finally{ + if(result!=null){ + try { + result.close(); + result = null; + } catch (SQLException e) { + e.printStackTrace(); + } + } + if(stmt!=null){ + try { + stmt.close(); + stmt = null; + } catch (SQLException e) { + e.printStackTrace(); + } + } + if(prest!=null){ + try { + prest.close(); + prest = null; + } catch (SQLException e) { + e.printStackTrace(); + } + } + if(connection!=null){ + try { + connection.close(); + connection = null; + } catch (SQLException e) { + e.printStackTrace(); + } + } + } + } + /** + * 推送提醒 + * @param type + * @param ids + */ + public void push(PhoneTypeEnum type,String[] ids){ + try { + Map map = new HashMap(); + map.put("timestamp", IfishUtil.format2(new Date())); + //推送android + if(type.equals(PhoneTypeEnum.android)){ + System.out.println(new Date()+"android推送"+ids.length+"个"); + jPushNotification.sendAndroidNotification(ids, "换水提醒", "您的水族箱需要换水啦~您可以在水箱设置中更改提醒设置", map); + } + //推送IOS + else if(type.equals(PhoneTypeEnum.ios)){ + System.out.println(new Date()+"ios推送"+ids.length+"个"); + jPushNotification2.sendIosNotification(ids, "换水提醒", "您的水族箱需要换水啦~您可以在水箱设置中更改提醒设置", map); + } + } catch (Exception e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/.svn/pristine/60/60a87169046c865c51affb11d969ba978310a34c.svn-base b/.svn/pristine/60/60a87169046c865c51affb11d969ba978310a34c.svn-base new file mode 100644 index 0000000..cc395ed --- /dev/null +++ b/.svn/pristine/60/60a87169046c865c51affb11d969ba978310a34c.svn-base @@ -0,0 +1,80 @@ +package com.ifish.jpush.examples; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.ifish.jpush.JPushClient; +import com.ifish.jpush.common.TimeUnit; +import com.ifish.jpush.common.resp.APIConnectionException; +import com.ifish.jpush.common.resp.APIRequestException; +import com.ifish.jpush.report.MessagesResult; +import com.ifish.jpush.report.ReceivedsResult; +import com.ifish.jpush.report.UsersResult; + +public class ReportsExample { + protected static final Logger LOG = LoggerFactory.getLogger(ReportsExample.class); + + // demo App defined in resources/jpush-api.conf + private static final String appKey = "dd1066407b044738b6479275"; + private static final String masterSecret = "2b38ce69b1de2a7fa95706ea"; + + public static void main(String[] args) { + testGetReport(); + testGetMessages(); + testGetUsers(); + } + + + public static void testGetReport() { + JPushClient jpushClient = new JPushClient(masterSecret, appKey); + try { + ReceivedsResult result = jpushClient.getReportReceiveds("1942377665"); + LOG.debug("Got result - " + result); + + } catch (APIConnectionException e) { + LOG.error("Connection error. Should retry later. ", e); + + } catch (APIRequestException e) { + LOG.error("Error response from JPush server. Should review and fix it. ", e); + LOG.info("HTTP Status: " + e.getStatus()); + LOG.info("Error Code: " + e.getErrorCode()); + LOG.info("Error Message: " + e.getErrorMessage()); + } + } + + public static void testGetUsers() { + JPushClient jpushClient = new JPushClient(masterSecret, appKey); + try { + UsersResult result = jpushClient.getReportUsers(TimeUnit.DAY, "2014-06-10", 3); + LOG.debug("Got result - " + result); + + } catch (APIConnectionException e) { + LOG.error("Connection error. Should retry later. ", e); + + } catch (APIRequestException e) { + LOG.error("Error response from JPush server. Should review and fix it. ", e); + LOG.info("HTTP Status: " + e.getStatus()); + LOG.info("Error Code: " + e.getErrorCode()); + LOG.info("Error Message: " + e.getErrorMessage()); + } + } + + public static void testGetMessages() { + JPushClient jpushClient = new JPushClient(masterSecret, appKey); + try { + MessagesResult result = jpushClient.getReportMessages("269978303"); + LOG.debug("Got result - " + result); + + } catch (APIConnectionException e) { + LOG.error("Connection error. Should retry later. ", e); + + } catch (APIRequestException e) { + LOG.error("Error response from JPush server. Should review and fix it. ", e); + LOG.info("HTTP Status: " + e.getStatus()); + LOG.info("Error Code: " + e.getErrorCode()); + LOG.info("Error Message: " + e.getErrorMessage()); + } + } + +} + diff --git a/.svn/pristine/62/6201507d19ad8dacf38e51d2238d7c5db8bfd643.svn-base b/.svn/pristine/62/6201507d19ad8dacf38e51d2238d7c5db8bfd643.svn-base new file mode 100644 index 0000000..d2e63ba --- /dev/null +++ b/.svn/pristine/62/6201507d19ad8dacf38e51d2238d7c5db8bfd643.svn-base @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.svn/pristine/63/631d4581f7a33113a805dfe147f1653f70dafea5.svn-base b/.svn/pristine/63/631d4581f7a33113a805dfe147f1653f70dafea5.svn-base new file mode 100644 index 0000000..f50674f --- /dev/null +++ b/.svn/pristine/63/631d4581f7a33113a805dfe147f1653f70dafea5.svn-base @@ -0,0 +1,187 @@ +package com.ifish.jpush.push.model.notification; + +import java.util.Map; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import com.ifish.jpush.common.ServiceHelper; + +/** + * APNs 通知类 + *

+ * 支持 APNs 默认的几个参数: + *

  • alert: 继承自父类 PlatformNotification 的 alert 属性;本类设置则覆盖。
  • + *
  • badge: 支持 setBadge(int) 方法来设置;支持 incrBadge(int) 方法来增加。
  • + *
  • sound: 支持 setSound(string) 方法来设置声音文件。
  • + *
  • content-available: 用来支持后台推送。如果该值赋值为 1,表示开启后台推送。
  • + *
  • extras: JSON object. 支持更多的自定义字段信息。
  • + *

    + *

    + * 需要特别留意的是,JPush SDK 会对以下几个值有特别的默认设置考虑: + *

  • badge: 默认为 "+1"。如果需要取消 badge 值,需要显式地调用 disableBadge().
  • + *
  • sound: 默认为 "",即默认的声音提示。如果需要取消 sound 值,即不要声音,需要显式地调用 disableSound().
  • + *

    + */ +public class IosNotification extends PlatformNotification { + public static final String NOTIFICATION_IOS = "ios"; + + private static final String DEFAULT_SOUND = ""; + private static final String DEFAULT_BADGE = "+1"; + + private static final String BADGE = "badge"; + private static final String SOUND = "sound"; + private static final String CONTENT_AVAILABLE = "content-available"; + private static final String CATEGORY = "category"; + + private static final String ALERT_VALID_BADGE = "Badge number should be 0~99999, " + + "and can be prefixed with + to add, - to minus"; + + + private final boolean soundDisabled; + private final boolean badgeDisabled; + private final String sound; + private final String badge; + private final boolean contentAvailable; + private final String category; + + private IosNotification(Object alert, String sound, String badge, + boolean contentAvailable, boolean soundDisabled, boolean badgeDisabled, + String category, + Map extras, + Map numberExtras, + Map booleanExtras, + Map jsonExtras) { + super(alert, extras, numberExtras, booleanExtras, jsonExtras); + + this.sound = sound; + this.badge = badge; + this.contentAvailable = contentAvailable; + this.soundDisabled = soundDisabled; + this.badgeDisabled = badgeDisabled; + this.category = category; + } + + public static Builder newBuilder() { + return new Builder(); + } + + public static IosNotification alert(String alert) { + return newBuilder().setAlert(alert).build(); + } + + + @Override + public String getPlatform() { + return NOTIFICATION_IOS; + } + + @Override + public JsonElement toJSON() { + JsonObject json = super.toJSON().getAsJsonObject(); + + if (!badgeDisabled) { + if (null != badge) { + json.add(BADGE, new JsonPrimitive(this.badge)); + } else { + json.add(BADGE, new JsonPrimitive(DEFAULT_BADGE)); + } + } + if (!soundDisabled) { + if (null != sound) { + json.add(SOUND, new JsonPrimitive(sound)); + } else { + json.add(SOUND, new JsonPrimitive(DEFAULT_SOUND)); + } + } + if (contentAvailable) { + json.add(CONTENT_AVAILABLE, new JsonPrimitive(1)); + } + if (null != category) { + json.add(CATEGORY, new JsonPrimitive(category)); + } + + return json; + } + + + public static class Builder extends PlatformNotification.Builder { + private String sound; + private String badge; + private boolean contentAvailable = false; + private boolean soundDisabled = false; + private boolean badgeDisabled = false; + private String category; + + protected Builder getThis() { + return this; + } + + public Builder setSound(String sound) { + this.sound = sound; + return this; + } + + public Builder disableSound() { + this.soundDisabled = true; + return this; + } + + public Builder incrBadge(int badge) { + if (!ServiceHelper.isValidIntBadge(Math.abs(badge))) { + LOG.warn(ALERT_VALID_BADGE); + return this; + } + + if (badge >= 0) { + this.badge = "+" + badge; + } else { + this.badge = "" + badge; + } + return this; + } + + public Builder setBadge(int badge) { + if (!ServiceHelper.isValidIntBadge(badge)) { + LOG.warn(ALERT_VALID_BADGE); + return this; + } + this.badge = "" + badge; + return this; + } + + /** + * equals to: +1 + */ + public Builder autoBadge() { + return incrBadge(1); + } + + public Builder disableBadge() { + this.badgeDisabled = true; + return this; + } + + public Builder setContentAvailable(boolean contentAvailable) { + this.contentAvailable = contentAvailable; + return this; + } + + public Builder setCategory(String category) { + this.category = category; + return this; + } + + public Builder setAlert(Object alert) { + this.alert = alert; + return this; + } + + + public IosNotification build() { + return new IosNotification(alert, sound, badge, contentAvailable, + soundDisabled, badgeDisabled, category, + extrasBuilder, numberExtrasBuilder, booleanExtrasBuilder, jsonExtrasBuilder); + } + } +} diff --git a/.svn/pristine/63/631ff26ec1bf8d8f5b15c9276de15a831a62352f.svn-base b/.svn/pristine/63/631ff26ec1bf8d8f5b15c9276de15a831a62352f.svn-base new file mode 100644 index 0000000..0f946ce --- /dev/null +++ b/.svn/pristine/63/631ff26ec1bf8d8f5b15c9276de15a831a62352f.svn-base @@ -0,0 +1,100 @@ + + + + + + + + + + + + + true + + + + + + + + + + + + + 0 0 10 * * ? + + + + + + + + + + + pushRemind + + + + + + + + + + + + + + + + + ${jpush.android.appKey} + + + + ${jpush.android.secret} + + + + ${jpush.android.productionMode} + + + + + + + ${jpush.ios.appKey} + + + + ${jpush.ios.secret} + + + + ${jpush.ios.productionMode} + + + + + + + ${netease.appKey} + + + + ${netease.appSecret} + + + \ No newline at end of file diff --git a/.svn/pristine/64/649559a0c05af8a170299eb54fd2c40f35448f25.svn-base b/.svn/pristine/64/649559a0c05af8a170299eb54fd2c40f35448f25.svn-base new file mode 100644 index 0000000..01904cf --- /dev/null +++ b/.svn/pristine/64/649559a0c05af8a170299eb54fd2c40f35448f25.svn-base @@ -0,0 +1,56 @@ +package com.ifish.util; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Random; + +public class IfishUtil { + + private static final String formatDate1 ="yyyy-MM-dd"; + private static final String formatDate2 ="yyyy-MM-dd HH:mm:ss"; + + /** + * 格式化日期yyyy-MM-dd HH:mm:ss + * @param date + * @return + */ + public static String format2(Date date){ + SimpleDateFormat format = new SimpleDateFormat(formatDate2); + return format.format(date); + } + + /** + * 格式化日期yyyy-MM-dd + * @param date + * @return + */ + public static String format1(Date date){ + SimpleDateFormat format = new SimpleDateFormat(formatDate1); + return format.format(date); + } + + /** + * 随机生成字母与数字组合 + * @param length + * @return + */ + public static String getCharAndNumr(int length) { + String val = ""; + Random random = new Random(); + for (int i = 0; i < length; i++) { + // 输出字母还是数字 + String charOrNum = random.nextInt(2) % 2 == 0 ? "char" : "num"; + // 字符串 + if ("char".equalsIgnoreCase(charOrNum)) { + // 取得大写字母还是小写字母 + int choice = random.nextInt(2) % 2 == 0 ? 65 : 97; + val += (char) (choice + random.nextInt(26)); + // 数字 + } else if ("num".equalsIgnoreCase(charOrNum)) { + val += String.valueOf(random.nextInt(10)); + } + } + return val; + } + +} diff --git a/.svn/pristine/64/64db1171fd4230a9eb95f09afa013aca0ed2ffaf.svn-base b/.svn/pristine/64/64db1171fd4230a9eb95f09afa013aca0ed2ffaf.svn-base new file mode 100644 index 0000000..3f3f12e --- /dev/null +++ b/.svn/pristine/64/64db1171fd4230a9eb95f09afa013aca0ed2ffaf.svn-base @@ -0,0 +1,48 @@ +package com.ifish.netease; + +import java.security.MessageDigest; + +/** + * SHA1(AppSecret + Nonce + CurTime),三个参数拼接的字符串,进行SHA1哈希计算,转化成16进制字符(String,小写) + * @author Administrator + * + */ +public class CheckSumBuilder { + + // 计算并获取CheckSum + public static String getCheckSum(String appSecret, String nonce, String curTime) { + return encode("sha1", appSecret + nonce + curTime); + } + + // 计算并获取md5值 + public static String getMD5(String requestBody) { + return encode("md5", requestBody); + } + + private static String encode(String algorithm, String value) { + if (value == null) { + return null; + } + try { + MessageDigest messageDigest + = MessageDigest.getInstance(algorithm); + messageDigest.update(value.getBytes()); + return getFormattedText(messageDigest.digest()); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private static String getFormattedText(byte[] bytes) { + int len = bytes.length; + StringBuilder buf = new StringBuilder(len * 2); + for (int j = 0; j < len; j++) { + buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]); + buf.append(HEX_DIGITS[bytes[j] & 0x0f]); + } + return buf.toString(); + } + + private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + +} \ No newline at end of file diff --git a/.svn/pristine/66/66e72c7a9f84587d8860056049fe3ce27f0e5bf9.svn-base b/.svn/pristine/66/66e72c7a9f84587d8860056049fe3ce27f0e5bf9.svn-base new file mode 100644 index 0000000..1a85939 --- /dev/null +++ b/.svn/pristine/66/66e72c7a9f84587d8860056049fe3ce27f0e5bf9.svn-base @@ -0,0 +1,117 @@ +package com.ifish.jpush.common; + +import java.util.HashMap; +import java.util.Map; + +public class ClientConfig extends HashMap { + + private static ClientConfig instance = new ClientConfig(); + + public static final String DEVICE_HOST_NAME = "device.host.name"; + public static final Object DEVICE_HOST_NAME_SCHEMA = String.class; + + public static final String DEVICES_PATH = "devices.path"; + public static final Object DEVICES_PATH_SCHEMA = String.class; + + public static final String TAGS_PATH = "tags.path"; + public static final Object TAGS_PATH_SCHEMA = String.class; + + public static final String ALIASES_PATH = "aliases.path"; + public static final Object ALIASES_PATH_SCHEMA = String.class; + + public static final String PUSH_HOST_NAME = "push.host.name"; + public static final Object PUSH_HOST_NAME_SCHEMA = String.class; + + public static final String PUSH_PATH = "push.path"; + public static final Object PUSH_PATH_SCHEMA = String.class; + + public static final String PUSH_VALIDATE_PATH = "push.validate.path"; + public static final Object PUSH_VALIDATE_PATH_SCHMEA = String.class; + + public static final String REPORT_HOST_NAME = "report.host.name"; + public static final Object REPORT_HOST_NAME_SCHEMA = String.class; + + public static final String REPORT_RECEIVE_PATH = "report.receive.path"; + public static final Object REPORT_RECEIVE_PATH_SCHEMA = String.class; + + public static final String REPORT_USER_PATH = "report.user.path"; + public static final Object REPORT_USER_PATH_SCHEMA = String.class; + + public static final String REPORT_MESSAGE_PATH = "report.message.path"; + public static final Object REPORT_MESSAGE_PATH_SCHEMA = String.class; + + public static final String SCHEDULE_HOST_NAME = "schedule.host.name"; + public static final Object SCHEDULE_HOST_NAME_SCHEMA = String.class; + + public static final String SCHEDULE_PATH = "schedule.path"; + public static final Object SCHEDULE_PATH_SCHEMA = String.class; + + private ClientConfig() { + super(12); + this.put(DEVICE_HOST_NAME, "https://device.jpush.cn"); + this.put(DEVICES_PATH, "/v3/devices"); + this.put(TAGS_PATH, "/v3/tags"); + this.put(ALIASES_PATH, "/v3/aliases"); + + this.put(PUSH_HOST_NAME, "https://api.jpush.cn"); + this.put(PUSH_PATH, "/v3/push"); + this.put(PUSH_VALIDATE_PATH, "/v3/push/validate"); + + this.put(REPORT_HOST_NAME, "https://report.jpush.cn"); + this.put(REPORT_RECEIVE_PATH, "/v3/received"); + this.put(REPORT_USER_PATH, "/v3/users"); + this.put(REPORT_MESSAGE_PATH, "/v3/messages"); + + this.put(SCHEDULE_HOST_NAME, "https://api.jpush.cn"); + this.put(SCHEDULE_PATH, "/v3/schedules"); + } + + public static ClientConfig getInstance() { + return instance; + } + + public static void setDeviceHostName(Map conf, String hostName) { + conf.put(DEVICE_HOST_NAME, hostName); + } + + /** + * Setup custom device api host name, if using the JPush privacy cloud. + * @param hostName the custom api host name, default is JPush domain name + */ + public void setDeviceHostName(String hostName) { + setDeviceHostName(this, hostName); + } + + public static void setPushHostName(Map conf, String hostName) { + conf.put(PUSH_HOST_NAME, hostName); + } + + /** + * Setup custom push api host name, if using the JPush privacy cloud. + * @param hostName the custom api host name, default is JPush domain name + */ + public void setPushHostName(String hostName) { + setPushHostName(this, hostName); + } + + public static void setReportHostName(Map conf, String hostName) { + conf.put(REPORT_HOST_NAME, hostName); + } + + /** + * Setup custom report api host name, if using the JPush privacy cloud. + * @param hostName the custom api host name, default is JPush domain name + */ + public void setReportHostName(String hostName) { + setReportHostName(this, hostName); + } + + public static void setScheduleHostName(Map conf, String hostName) { + conf.put(SCHEDULE_HOST_NAME, hostName); + } + + public void setScheduleHostName(String hostName) { + setScheduleHostName(this, hostName); + } + +} diff --git a/.svn/pristine/67/671861cd430b74a11fb2bcc6b6da90f9667b652a.svn-base b/.svn/pristine/67/671861cd430b74a11fb2bcc6b6da90f9667b652a.svn-base new file mode 100644 index 0000000..b921731 --- /dev/null +++ b/.svn/pristine/67/671861cd430b74a11fb2bcc6b6da90f9667b652a.svn-base @@ -0,0 +1,244 @@ +package com.ifish.netease; + +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.http.HttpResponse; +import org.apache.http.NameValuePair; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.ifish.enums.NeteaseEnum; +import com.ifish.util.IfishUtil; + +public class NeteaseIM { + + String appKey = ""; + String appSecret = ""; + + private static Logger log = LoggerFactory.getLogger(NeteaseIM.class); + + public NeteaseIM(String appKey,String appSecret){ + this.appKey=appKey; + this.appSecret=appSecret; + } + /** + * 创建云信ID + * @param accid 云信ID,最大长度32字符,必须保证一个APP内唯一 + * @param name 云信ID昵称,最大长度64字符,用来PUSH推送 时显示的昵称 + * @param icon 云信ID头像URL,第三方可选填,最大长度1024 + * @param props json属性,第三方可选填,最大长度1024字符 + * @return + * @throws Exception + */ + public Map createAccid(String accid,String name,String icon,String props){ + try { + DefaultHttpClient httpClient = new DefaultHttpClient(); + String url = "https://api.netease.im/nimserver/user/create.action"; + HttpPost httpPost = new HttpPost(url); + String nonce = IfishUtil.getCharAndNumr(10); + String curTime = String.valueOf((new Date()).getTime() / 1000L); + //计算CheckSum + String checkSum = CheckSumBuilder.getCheckSum(appSecret, nonce ,curTime); + //设置请求的header + httpPost.addHeader("AppKey", appKey); + httpPost.addHeader("Nonce", nonce); + httpPost.addHeader("CurTime", curTime); + httpPost.addHeader("CheckSum", checkSum); + httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8"); + //设置请求的参数 + List nvps = new ArrayList(); + nvps.add(new BasicNameValuePair("accid", accid)); + nvps.add(new BasicNameValuePair("name", name)); + nvps.add(new BasicNameValuePair("icon", icon)); + nvps.add(new BasicNameValuePair("props", props)); + httpPost.setEntity(new UrlEncodedFormEntity(nvps, "utf-8")); + //执行请求 + HttpResponse response = httpClient.execute(httpPost); + //执行结果 + String responseStr = EntityUtils.toString(response.getEntity(), "utf-8"); + JSONObject json = new JSONObject(responseStr); + String code = json.getString("code"); + Map map = new HashMap(); + map.put("code", code); + //200 + if(code.equals(NeteaseEnum.status200.getKey())){ + JSONObject infoJson = json.getJSONObject("info"); + String token = infoJson.getString("token"); + map.put("token", token); + } + else if(code.equals(NeteaseEnum.status414.getKey())){ + String desc = json.getString("desc"); + } + return map; + } catch (Exception e) { + log.error("CreateAccid error message:{},{}",accid,e.toString()); + } + return null; + } + /** + * 更新并获取新token + * @param accid + * @return + * @throws Exception + */ + public Map refreshToken(String accid){ + try { + DefaultHttpClient httpClient = new DefaultHttpClient(); + String url = "https://api.netease.im/nimserver/user/refreshToken.action"; + HttpPost httpPost = new HttpPost(url); + String nonce = IfishUtil.getCharAndNumr(10); + String curTime = String.valueOf((new Date()).getTime() / 1000L); + //计算CheckSum + String checkSum = CheckSumBuilder.getCheckSum(appSecret, nonce ,curTime); + //设置请求的header + httpPost.addHeader("AppKey", appKey); + httpPost.addHeader("Nonce", nonce); + httpPost.addHeader("CurTime", curTime); + httpPost.addHeader("CheckSum", checkSum); + httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8"); + //设置请求的参数 + List nvps = new ArrayList(); + nvps.add(new BasicNameValuePair("accid", accid)); + httpPost.setEntity(new UrlEncodedFormEntity(nvps, "utf-8")); + //执行请求 + HttpResponse response = httpClient.execute(httpPost); + //执行结果 + String responseStr = EntityUtils.toString(response.getEntity(), "utf-8"); + JSONObject json = new JSONObject(responseStr); + String code = json.getString("code"); + Map map = new HashMap(); + map.put("code", code); + //200 + if(code.equals(NeteaseEnum.status200.getKey())){ + JSONObject infoJson = json.getJSONObject("info"); + String token = infoJson.getString("token"); + map.put("token", token); + } + else if(code.equals(NeteaseEnum.status414.getKey())){ + String desc = json.getString("desc"); + } + return map; + } catch (Exception e) { + log.error("refreshToken error message:{},{}",accid,e.toString()); + } + return null; + } + + /** + * 发送普通消息 + * @param from + * @param to + * @param msg + * @return + */ + public Map sendMsg(String from,String to,String msg){ + try { + DefaultHttpClient httpClient = new DefaultHttpClient(); + String url = "https://api.netease.im/nimserver/msg/sendMsg.action"; + HttpPost httpPost = new HttpPost(url); + String nonce = IfishUtil.getCharAndNumr(10); + String curTime = String.valueOf((new Date()).getTime() / 1000L); + //计算CheckSum + String checkSum = CheckSumBuilder.getCheckSum(appSecret, nonce ,curTime); + //设置请求的header + httpPost.addHeader("AppKey", appKey); + httpPost.addHeader("Nonce", nonce); + httpPost.addHeader("CurTime", curTime); + httpPost.addHeader("CheckSum", checkSum); + httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8"); + //设置请求的参数 + List nvps = new ArrayList(); + nvps.add(new BasicNameValuePair("from", from)); + nvps.add(new BasicNameValuePair("to", to)); + nvps.add(new BasicNameValuePair("ope", "0")); + nvps.add(new BasicNameValuePair("type", "0")); + nvps.add(new BasicNameValuePair("body", "{\"msg\":\""+msg+"\"}")); + httpPost.setEntity(new UrlEncodedFormEntity(nvps, "utf-8")); + //执行请求 + HttpResponse response = httpClient.execute(httpPost); + //执行结果 + String responseStr = EntityUtils.toString(response.getEntity(), "utf-8"); + JSONObject json = new JSONObject(responseStr); + String code = json.getString("code"); + Map map = new HashMap(); + map.put("code", code); + //200 + if(code.equals(NeteaseEnum.status200.getKey())){ + + } + else if(code.equals(NeteaseEnum.status414.getKey())){ + String desc = json.getString("desc"); + } + return map; + } catch (Exception e) { + log.error("refreshToken error message:{}",e.toString()); + } + return null; + } + /** + * 批量发送点对点普通消息 + * @param fromAccid + * @param toAccids + * @param msg + * @return + */ + public Map sendBatchMsg(String fromAccid,String toAccids,String msg){ + try { + DefaultHttpClient httpClient = new DefaultHttpClient(); + String url = "https://api.netease.im/nimserver/msg/sendBatchMsg.action"; + HttpPost httpPost = new HttpPost(url); + String nonce = IfishUtil.getCharAndNumr(10); + String curTime = String.valueOf((new Date()).getTime() / 1000L); + //计算CheckSum + String checkSum = CheckSumBuilder.getCheckSum(appSecret, nonce ,curTime); + //设置请求的header + httpPost.addHeader("AppKey", appKey); + httpPost.addHeader("Nonce", nonce); + httpPost.addHeader("CurTime", curTime); + httpPost.addHeader("CheckSum", checkSum); + httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8"); + //设置请求的参数 + List nvps = new ArrayList(); + nvps.add(new BasicNameValuePair("fromAccid", fromAccid)); + nvps.add(new BasicNameValuePair("toAccids", toAccids)); + nvps.add(new BasicNameValuePair("type", "0")); + nvps.add(new BasicNameValuePair("body", "{\"msg\":\""+msg+"\"}")); + httpPost.setEntity(new UrlEncodedFormEntity(nvps, "utf-8")); + //执行请求 + HttpResponse response = httpClient.execute(httpPost); + //执行结果 + String responseStr = EntityUtils.toString(response.getEntity(), "utf-8"); + JSONObject json = new JSONObject(responseStr); + String code = json.getString("code"); + Map map = new HashMap(); + map.put("code", code); + //200 + if(code.equals(NeteaseEnum.status200.getKey())){ + + } + else if(code.equals(NeteaseEnum.status414.getKey())){ + String desc = json.getString("desc"); + } + return map; + } catch (Exception e) { + log.error("refreshToken error message:{}",e.toString()); + } + return null; + } + public static void main(String[] args) { + List list= new ArrayList(); + list.add("hello"); + list.add("hello1"); + new NeteaseIM("87b0e3315dfc2df08060bcb54246da68", "e62f6c247b46").createAccid("ifish", "爱鱼奇", "", ""); + } +} diff --git a/.svn/pristine/68/68ca41ed890bd786cc693f5f9b3dd33bf2dbe899.svn-base b/.svn/pristine/68/68ca41ed890bd786cc693f5f9b3dd33bf2dbe899.svn-base new file mode 100644 index 0000000..b72a6a4 --- /dev/null +++ b/.svn/pristine/68/68ca41ed890bd786cc693f5f9b3dd33bf2dbe899.svn-base @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.svn/pristine/6b/6b269cbfa4da94a75dbf9b94be3e12d05a59fb94.svn-base b/.svn/pristine/6b/6b269cbfa4da94a75dbf9b94be3e12d05a59fb94.svn-base new file mode 100644 index 0000000..98c1561 --- /dev/null +++ b/.svn/pristine/6b/6b269cbfa4da94a75dbf9b94be3e12d05a59fb94.svn-base @@ -0,0 +1,50 @@ +package com.ifish.jpush.report; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.List; + +import com.google.gson.annotations.Expose; +import com.google.gson.reflect.TypeToken; +import com.ifish.jpush.common.resp.BaseResult; +import com.ifish.jpush.common.resp.ResponseWrapper; + +public class MessagesResult extends BaseResult { + private static final Type MESSAGE_TYPE = new TypeToken>(){}.getType(); + + @Expose public List messages = new ArrayList(); + + public static class Message { + @Expose public long msg_id; + @Expose public Android android; + @Expose public Ios ios; + } + + public static class Android { + @Expose public int received; + @Expose public int target; + @Expose public int online_push; + @Expose public int click; + @Expose public int msg_click; + } + + public static class Ios { + @Expose public int apns_sent; + @Expose public int apns_target; + @Expose public int click; + @Expose public int target; + @Expose public int received; + @Expose public int msg_click; + } + + static MessagesResult fromResponse(ResponseWrapper responseWrapper) { + MessagesResult result = new MessagesResult(); + if (responseWrapper.isServerResponse()) { + result.messages = _gson.fromJson(responseWrapper.responseContent, MESSAGE_TYPE); + } + + result.setResponseWrapper(responseWrapper); + return result; + } + +} diff --git a/.svn/pristine/6e/6e73607a9b0ef41ec4eb3407f8993c7d6c3ec9b6.svn-base b/.svn/pristine/6e/6e73607a9b0ef41ec4eb3407f8993c7d6c3ec9b6.svn-base new file mode 100644 index 0000000..1cafa0a --- /dev/null +++ b/.svn/pristine/6e/6e73607a9b0ef41ec4eb3407f8993c7d6c3ec9b6.svn-base @@ -0,0 +1,171 @@ + + 4.0.0 + quartzPro + quartzPro + war + 0.0.1-SNAPSHOT + quartzPro + http://mvnrepository.com + + + + + org.quartz-scheduler + quartz + 2.2.1 + + + + javax.servlet + javax.servlet-api + 3.0.1 + + + + org.springframework + spring-core + 4.1.6.RELEASE + + + + org.springframework + spring-context + 4.1.6.RELEASE + + + + org.springframework + spring-context-support + 4.1.6.RELEASE + + + + org.aspectj + aspectjweaver + 1.8.5 + + + + org.springframework + spring-aspects + 4.1.6.RELEASE + + + + org.springframework + spring-orm + 4.1.6.RELEASE + + + + org.springframework + spring-beans + 4.1.6.RELEASE + + + + org.springframework + spring-aop + 4.1.6.RELEASE + + + + org.springframework + spring-webmvc + 4.1.6.RELEASE + + + + c3p0 + c3p0 + 0.9.1.2 + + + + org.slf4j + slf4j-api + 1.7.12 + + + + ch.qos.logback + logback-core + 1.1.2 + + + + ch.qos.logback + logback-classic + 1.1.2 + + + + org.hibernate + hibernate-core + 4.3.11.Final + + + + org.jboss.logging + jboss-logging-annotations + 2.0.1.Final + + + + org.json + json + 20090211 + + + + com.google.code.gson + gson + 2.3 + + + + + quartzPro + + + org.apache.maven.plugins + maven-war-plugin + 2.4 + + + + src/main/webapp + + + + + + org.apache.felix + maven-bundle-plugin + 2.5.4 + true + + + + + src/main/java + + **/*.hbm.xml + + + + src/main/resources + + **/*.xml + **/*.properties + + + + + + + UTF-8 + + + diff --git a/.svn/pristine/6e/6e76c275af537415d061621be569e8242349ec70.svn-base b/.svn/pristine/6e/6e76c275af537415d061621be569e8242349ec70.svn-base new file mode 100644 index 0000000..b0597b8 --- /dev/null +++ b/.svn/pristine/6e/6e76c275af537415d061621be569e8242349ec70.svn-base @@ -0,0 +1,44 @@ +package com.ifish.jpush; + +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.JsonObject; +import com.ifish.jpush.common.resp.APIConnectionException; +import com.ifish.jpush.common.resp.APIRequestException; +import com.ifish.jpush.push.PushResult; + +public class JPushNotification { + + protected final Logger LOG = LoggerFactory.getLogger(JPushNotification.class); + JPushClient jpushClient = null; + + public JPushNotification(String appKey,String masterSecret,boolean productionModel){ + jpushClient = new JPushClient(masterSecret, appKey , productionModel ,86400); + } + + public void sendIosNotification(String[] alias,String title,String body,Map extras) { + try { + JsonObject json = new JsonObject(); + json.addProperty("title", title); + json.addProperty("body", body); + PushResult result = jpushClient.sendIosNotificationWithAlias(json, extras, alias); + } catch (APIConnectionException e) { + LOG.error("Connection error. Should retry later. ", e); + } catch (APIRequestException e) { + LOG.error("Error Message: " + e.getMessage()); + } + } + + public void sendAndroidNotification(String[] alias,String title,String alert,Map map) { + try { + PushResult result = jpushClient.sendAndroidNotificationWithAlias(title ,alert, map, alias); + } catch (APIConnectionException e) { + LOG.error("Connection error. Should retry later. ", e); + } catch (APIRequestException e) { + LOG.error("Error Message: " + e.getMessage()); + } + } +} diff --git a/.svn/pristine/6f/6f79b839cd0302e09ffd3da52bcb7c3b1225a949.svn-base b/.svn/pristine/6f/6f79b839cd0302e09ffd3da52bcb7c3b1225a949.svn-base new file mode 100644 index 0000000..8bdb565 --- /dev/null +++ b/.svn/pristine/6f/6f79b839cd0302e09ffd3da52bcb7c3b1225a949.svn-base @@ -0,0 +1,44 @@ +package com.ifish.jpush; + +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.JsonObject; +import com.ifish.jpush.common.resp.APIConnectionException; +import com.ifish.jpush.common.resp.APIRequestException; +import com.ifish.jpush.push.PushResult; + +public class JPushNotification { + + protected final Logger LOG = LoggerFactory.getLogger(JPushNotification.class); + JPushClient jpushClient = null; + + public JPushNotification(String appKey,String masterSecret,boolean productionModel){ + jpushClient = new JPushClient(masterSecret, appKey , productionModel ,86400); + } + + public void sendIosNotification(String[] alias,String title,String body,Map extras) { + try { + JsonObject json = new JsonObject(); + json.addProperty("title", title); + json.addProperty("body", body); + PushResult result = jpushClient.sendIosNotificationWithAlias(json, extras, alias); + } catch (APIConnectionException e) { + LOG.error("Connection error. Should retry later. ", e); + } catch (APIRequestException e) { + LOG.error("Error Message: " + e.getMessage()); + } + } + + /*public void sendAndroidNotification(String[] alias,String title,String alert,Map map) { + try { + PushResult result = jpushClient.sendAndroidNotificationWithAlias(title ,alert, map, alias); + } catch (APIConnectionException e) { + LOG.error("Connection error. Should retry later. ", e); + } catch (APIRequestException e) { + LOG.error("Error Message: " + e.getMessage()); + } + }*/ +} diff --git a/.svn/pristine/6f/6fd352e9c173ab88f700f49b87e2c0304dd454b0.svn-base b/.svn/pristine/6f/6fd352e9c173ab88f700f49b87e2c0304dd454b0.svn-base new file mode 100644 index 0000000..e68c450 --- /dev/null +++ b/.svn/pristine/6f/6fd352e9c173ab88f700f49b87e2c0304dd454b0.svn-base @@ -0,0 +1,109 @@ +package com.ifish.jpush.common.resp; + +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.JsonSyntaxException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ResponseWrapper { + private static final Logger LOG = LoggerFactory.getLogger(ResponseWrapper.class); + private static final int RESPONSE_CODE_NONE = -1; + + private static Gson _gson = new Gson(); + private static JsonParser jsonParser = new JsonParser(); + + public int responseCode = RESPONSE_CODE_NONE; + public String responseContent; + + public ErrorObject error; // error for non-200 response, used by new API + + public int rateLimitQuota; + public int rateLimitRemaining; + public int rateLimitReset; + + public void setRateLimit(String quota, String remaining, String reset) { + if (null == quota) return; + + try { + rateLimitQuota = Integer.parseInt(quota); + rateLimitRemaining = Integer.parseInt(remaining); + rateLimitReset = Integer.parseInt(reset); + + LOG.debug("JPush API Rate Limiting params - quota:" + quota + ", remaining:" + remaining + ", reset:" + reset); + } catch (NumberFormatException e) { + LOG.debug("Unexpected - parse rate limiting headers error."); + } + } + + public void setErrorObject() { + error = new ErrorObject(); + error.error = new ErrorEntity(); + try { + JsonElement element = jsonParser.parse(responseContent); + JsonObject errorObj = null; + if( element instanceof JsonArray) { + JsonArray array = (JsonArray) element; + for(int i = 0; i < array.size(); i++) { + if(array.get(i).getAsJsonObject().has("error")) { + errorObj = array.get(i).getAsJsonObject(); + break; + } + } + } else if(element instanceof JsonObject) { + errorObj = (JsonObject) element; + } else { + // nothing + } + if(null != errorObj) { + JsonObject errorMsg = errorObj; + if(errorObj.has("msg_id")) { + error.msg_id = errorObj.get("msg_id").getAsLong(); + } + if (errorObj.has("error")) { + errorMsg = (JsonObject) errorObj.get("error"); + } + if(errorMsg.has("code")) { + error.error.code = errorMsg.get("code").getAsInt(); + } + if(errorMsg.has("message")) { + error.error.message = errorMsg.get("message").getAsString(); + } + } + } catch(JsonSyntaxException e) { + LOG.error("Unexpected - responseContent:" + responseContent, e); + } catch (Exception e) { + LOG.error("Unexpected - responseContent:" + responseContent, e); + } + } + + public boolean isServerResponse() { + if (responseCode / 100 == 2) return true; + if (responseCode > 0 && null != error && error.error.code > 0) return true; + return false; + } + + @Override + public String toString() { + return _gson.toJson(this); + } + + public static class ErrorObject { + public long msg_id; + public ErrorEntity error; + } + + public static class ErrorEntity { + public int code; + public String message; + + @Override + public String toString() { + return _gson.toJson(this); + } + } + +} diff --git a/.svn/pristine/71/71cf754c9cab170b77bef1e64c6da6be626ea99c.svn-base b/.svn/pristine/71/71cf754c9cab170b77bef1e64c6da6be626ea99c.svn-base new file mode 100644 index 0000000..a67e5de --- /dev/null +++ b/.svn/pristine/71/71cf754c9cab170b77bef1e64c6da6be626ea99c.svn-base @@ -0,0 +1,93 @@ +package com.ifish.jpush.common; + +import java.text.SimpleDateFormat; +import java.util.Random; +import java.util.Set; +import java.util.regex.Pattern; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.JsonArray; +import com.google.gson.JsonPrimitive; +import com.ifish.jpush.utils.Base64; +import com.ifish.jpush.utils.StringUtils; + +public class ServiceHelper { + + private static final Logger LOG = LoggerFactory.getLogger(ServiceHelper.class); + private final static Pattern PUSH_PATTERNS = Pattern.compile("[^a-zA-Z0-9]"); + private final static String BASIC_PREFIX = "Basic"; + + private static final Random RANDOM = new Random(System.currentTimeMillis()); + private static final int MIN = 100000; + private static final int MAX = Integer.MAX_VALUE; + + private static final int MAX_BADGE_NUMBER = 99999; + + private static final Pattern USERNAME_PATTERN = Pattern.compile("^[a-zA-Z0-9][a-zA-Z_0-9.、。@,-]*"); + private static final Pattern DATE_PATTERN = Pattern.compile("[0-9]{4}-[0-9]{2}-[0-9]{2}"); + private static final String DATE_FORMAT = "yyyy-MM-dd"; + + + public static boolean isValidIntBadge(int intBadge) { + if (intBadge >= 0 && intBadge <= MAX_BADGE_NUMBER) { + return true; + } + return false; + } + + public static int generateSendno() { + return RANDOM.nextInt((MAX - MIN) + 1) + MIN; + } + + public static String getBasicAuthorization(String username, String password) { + String encodeKey = username + ":" + password; + return BASIC_PREFIX + " " + String.valueOf(Base64.encode(encodeKey.getBytes())); + } + + public static void checkBasic(String appKey, String masterSecret) { + if (StringUtils.isEmpty(appKey) + || StringUtils.isEmpty(masterSecret)) { + throw new IllegalArgumentException("appKey and masterSecret are both required."); + } + if (appKey.length() != 24 + || masterSecret.length() != 24 + || PUSH_PATTERNS.matcher(appKey).find() + || PUSH_PATTERNS.matcher(masterSecret).find()) { + throw new IllegalArgumentException("appKey and masterSecret format is incorrect. " + + "They should be 24 size, and be composed with alphabet and numbers. " + + "Please confirm that they are coming from JPush Web Portal."); + } + } + + public static JsonArray fromSet(Set sets) { + JsonArray array = new JsonArray(); + if (null != sets && sets.size() > 0) { + for (String item : sets) { + array.add(new JsonPrimitive(item)); + } + } + return array; + } + + public static boolean checkUsername(String username) { + return USERNAME_PATTERN.matcher(username).matches(); + } + + public static boolean isValidBirthday( String birthday) { + try { + if( ! DATE_PATTERN.matcher(birthday).matches() ) { + return false; + } + SimpleDateFormat format = new SimpleDateFormat(DATE_FORMAT); + format.setLenient(false); + format.parse(birthday); + } catch (Exception e) { + LOG.error("incorrect date format. " + birthday, e); + return false; + } + return true; + } + +} diff --git a/.svn/pristine/75/75d9fb5006403e80b4f17b07a090d20256213c4d.svn-base b/.svn/pristine/75/75d9fb5006403e80b4f17b07a090d20256213c4d.svn-base new file mode 100644 index 0000000..72eb823 --- /dev/null +++ b/.svn/pristine/75/75d9fb5006403e80b4f17b07a090d20256213c4d.svn-base @@ -0,0 +1,33 @@ +package com.ifish.enums; + +public enum PushTypeEnum { + remove_device("remove_device","解除设备"), + wendu_warn("wendu_warn","温度报警"), + qu_reply("qu_reply","问题反馈"), + app_update("app_update","IOS更新推送"), + remind_water("remind_water","换水提醒"), + offline_push("offline_push","设备离线推送"); + + private PushTypeEnum(String key,String value){ + this.key = key; + this.value = value; + } + + private String key; + private String value; + + + public String getKey() { + return key; + } + public void setKey(String key) { + this.key = key; + } + public String getValue() { + return value; + } + public void setValue(String value) { + this.value = value; + } + +} diff --git a/.svn/pristine/76/76e1f90e3b569c35076b9055ccccae2535e84c80.svn-base b/.svn/pristine/76/76e1f90e3b569c35076b9055ccccae2535e84c80.svn-base new file mode 100644 index 0000000..635bfdd --- /dev/null +++ b/.svn/pristine/76/76e1f90e3b569c35076b9055ccccae2535e84c80.svn-base @@ -0,0 +1,73 @@ +package com.ifish.jpush.common.resp; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.ifish.jpush.common.resp.ResponseWrapper.ErrorObject; + +public class APIRequestException extends Exception implements IRateLimiting { + private static final long serialVersionUID = -3921022835186996212L; + + protected static Gson _gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create(); + + private final ResponseWrapper responseWrapper; + + public APIRequestException(ResponseWrapper responseWrapper) { + super(responseWrapper.responseContent); + this.responseWrapper = responseWrapper; + } + + public int getStatus() { + return this.responseWrapper.responseCode; + } + + public long getMsgId() { + ErrorObject eo = getErrorObject(); + if (null != eo) { + return eo.msg_id; + } + return 0; + } + + public int getErrorCode() { + ErrorObject eo = getErrorObject(); + if (null != eo && null != eo.error) { + return eo.error.code; + } + return -1; + } + + public String getErrorMessage() { + ErrorObject eo = getErrorObject(); + if (null != eo && null != eo.error) { + return eo.error.message; + } + return null; + } + + @Override + public String toString() { + return _gson.toJson(this); + } + + private ErrorObject getErrorObject() { + return this.responseWrapper.error; + } + + + @Override + public int getRateLimitQuota() { + return responseWrapper.rateLimitQuota; + } + + @Override + public int getRateLimitRemaining() { + return responseWrapper.rateLimitRemaining; + } + + @Override + public int getRateLimitReset() { + return responseWrapper.rateLimitReset; + } + +} + diff --git a/.svn/pristine/7b/7b36cbc1f5643a74a6b8ba9bb39ffa3f00eb88c2.svn-base b/.svn/pristine/7b/7b36cbc1f5643a74a6b8ba9bb39ffa3f00eb88c2.svn-base new file mode 100644 index 0000000..309c43f --- /dev/null +++ b/.svn/pristine/7b/7b36cbc1f5643a74a6b8ba9bb39ffa3f00eb88c2.svn-base @@ -0,0 +1,89 @@ + + + + + + + + + + + + + true + + + + + + + + + + + + + 0 0 10 * * ? + + + + + + + + + + + pushRemind + + + + + + + + + + + + + + + + + ${jpush.android.appKey} + + + + ${jpush.android.secret} + + + + ${jpush.android.productionMode} + + + + + + + ${jpush.ios.appKey} + + + + ${jpush.ios.secret} + + + + ${jpush.ios.productionMode} + + + \ No newline at end of file diff --git a/.svn/pristine/7e/7ec87a3de551bed151b31663853d69df85485ca5.svn-base b/.svn/pristine/7e/7ec87a3de551bed151b31663853d69df85485ca5.svn-base new file mode 100644 index 0000000..33731d4 --- /dev/null +++ b/.svn/pristine/7e/7ec87a3de551bed151b31663853d69df85485ca5.svn-base @@ -0,0 +1,83 @@ +package com.ifish.jpush.schedule.model; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.ifish.jpush.push.model.PushPayload; +import com.ifish.jpush.utils.StringUtils; + +public class SchedulePayload implements IModel { + + private static Gson gson = new Gson(); + + private String name; + private Boolean enabled; + private TriggerPayload trigger; + private PushPayload push; + + private SchedulePayload(String name, Boolean enabled, TriggerPayload trigger, PushPayload push) { + this.name = name; + this.enabled = enabled; + this.trigger = trigger; + this.push = push; + } + + public static Builder newBuilder() { + return new Builder(); + } + + @Override + public JsonElement toJSON() { + JsonObject json = new JsonObject(); + if ( StringUtils.isNotEmpty(name) ) { + json.addProperty("name", name); + } + if ( null != enabled ) { + json.addProperty("enabled", enabled); + } + if ( null != trigger ) { + json.add("trigger", trigger.toJSON()); + } + if ( null != push ) { + json.add("push", push.toJSON()); + } + return json; + } + + @Override + public String toString() { + return gson.toJson(toJSON()); + } + + public static class Builder{ + private String name; + private Boolean enabled; + private TriggerPayload trigger; + private PushPayload push; + + public Builder setName(String name) { + this.name = name; + return this; + } + + public Builder setEnabled(Boolean enabled) { + this.enabled = enabled; + return this; + } + + public Builder setTrigger(TriggerPayload trigger) { + this.trigger = trigger; + return this; + } + + public Builder setPush(PushPayload push) { + this.push = push; + return this; + } + + public SchedulePayload build() { + + return new SchedulePayload(name, enabled, trigger, push); + } + } +} diff --git a/.svn/pristine/7e/7ef99a7253834cab6795a0722b4c3bbdddfaf460.svn-base b/.svn/pristine/7e/7ef99a7253834cab6795a0722b4c3bbdddfaf460.svn-base new file mode 100644 index 0000000..fa88549 --- /dev/null +++ b/.svn/pristine/7e/7ef99a7253834cab6795a0722b4c3bbdddfaf460.svn-base @@ -0,0 +1,439 @@ +/* + * Copyright (C) 2007 The Guava Authors + * + * 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.ifish.jpush.utils; + +/** + * Copied from Google Guava. + * + * Static convenience methods that help a method or constructor check whether it was invoked + * correctly (whether its preconditions have been met). These methods generally accept a + * {@code boolean} expression which is expected to be {@code true} (or in the case of {@code + * checkNotNull}, an object reference which is expected to be non-null). When {@code false} (or + * {@code null}) is passed instead, the {@code Preconditions} method throws an unchecked exception, + * which helps the calling method communicate to its caller that that caller has made + * a mistake. Example:
       {@code
    + *
    + *   /**
    + *    * Returns the positive square root of the given value.
    + *    *
    + *    * @throws IllegalArgumentException if the value is negative
    + *    *}{@code /
    + *   public static double sqrt(double value) {
    + *     Preconditions.checkArgument(value >= 0.0, "negative value: %s", value);
    + *     // calculate the square root
    + *   }
    + *
    + *   void exampleBadCaller() {
    + *     double d = sqrt(-1.0);
    + *   }}
    + * + * In this example, {@code checkArgument} throws an {@code IllegalArgumentException} to indicate + * that {@code exampleBadCaller} made an error in its call to {@code sqrt}. + * + *

    Warning about performance

    + * + *

    The goal of this class is to improve readability of code, but in some circumstances this may + * come at a significant performance cost. Remember that parameter values for message construction + * must all be computed eagerly, and autoboxing and varargs array creation may happen as well, even + * when the precondition check then succeeds (as it should almost always do in production). In some + * circumstances these wasted CPU cycles and allocations can add up to a real problem. + * Performance-sensitive precondition checks can always be converted to the customary form: + *

       {@code
    + *
    + *   if (value < 0.0) {
    + *     throw new IllegalArgumentException("negative value: " + value);
    + *   }}
    + * + *

    Other types of preconditions

    + * + *

    Not every type of precondition failure is supported by these methods. Continue to throw + * standard JDK exceptions such as {@link java.util.NoSuchElementException} or {@link + * UnsupportedOperationException} in the situations they are intended for. + * + *

    Non-preconditions

    + * + *

    It is of course possible to use the methods of this class to check for invalid conditions + * which are not the caller's fault. Doing so is not recommended because it is + * misleading to future readers of the code and of stack traces. See + * Conditional + * failures explained in the Guava User Guide for more advice. + * + *

    {@code java.util.Objects.requireNonNull()}

    + * + *

    Projects which use {@code com.google.common} should generally avoid the use of {@link + * java.util.Objects#requireNonNull(Object)}. Instead, use whichever of {@link + * #checkNotNull(Object)} or {@link Verify#verifyNotNull(Object)} is appropriate to the situation. + * (The same goes for the message-accepting overloads.) + * + *

    Only {@code %s} is supported

    + * + *

    In {@code Preconditions} error message template strings, only the {@code "%s"} specifier is + * supported, not the full range of {@link java.util.Formatter} specifiers. However, note that if + * the number of arguments does not match the number of occurrences of {@code "%s"} in the format + * string, {@code Preconditions} will still behave as expected, and will still include all argument + * values in the error message; the message will simply not be formatted exactly as intended. + * + *

    More information

    + * + *

    See the Guava User Guide on + * using {@code + * Preconditions}. + * + * @author Kevin Bourrillion + * @since 2.0 (imported from Google Collections Library) + */ +public final class Preconditions { + private Preconditions() {} + + /** + * Ensures the truth of an expression involving one or more parameters to the calling method. + * + * @param expression a boolean expression + * @throws IllegalArgumentException if {@code expression} is false + */ + public static void checkArgument(boolean expression) { + if (!expression) { + throw new IllegalArgumentException(); + } + } + + /** + * Ensures the truth of an expression involving one or more parameters to the calling method. + * + * @param expression a boolean expression + * @param errorMessage the exception message to use if the check fails; will be converted to a + * string using {@link String#valueOf(Object)} + * @throws IllegalArgumentException if {@code expression} is false + */ + public static void checkArgument(boolean expression, @Nullable Object errorMessage) { + if (!expression) { + throw new IllegalArgumentException(String.valueOf(errorMessage)); + } + } + + /** + * Ensures the truth of an expression involving one or more parameters to the calling method. + * + * @param expression a boolean expression + * @param errorMessageTemplate a template for the exception message should the check fail. The + * message is formed by replacing each {@code %s} placeholder in the template with an + * argument. These are matched by position - the first {@code %s} gets {@code + * errorMessageArgs[0]}, etc. Unmatched arguments will be appended to the formatted message + * in square braces. Unmatched placeholders will be left as-is. + * @param errorMessageArgs the arguments to be substituted into the message template. Arguments + * are converted to strings using {@link String#valueOf(Object)}. + * @throws IllegalArgumentException if {@code expression} is false + * @throws NullPointerException if the check fails and either {@code errorMessageTemplate} or + * {@code errorMessageArgs} is null (don't let this happen) + */ + public static void checkArgument(boolean expression, + @Nullable String errorMessageTemplate, + @Nullable Object... errorMessageArgs) { + if (!expression) { + throw new IllegalArgumentException(format(errorMessageTemplate, errorMessageArgs)); + } + } + + /** + * Ensures the truth of an expression involving the state of the calling instance, but not + * involving any parameters to the calling method. + * + * @param expression a boolean expression + * @throws IllegalStateException if {@code expression} is false + */ + public static void checkState(boolean expression) { + if (!expression) { + throw new IllegalStateException(); + } + } + + /** + * Ensures the truth of an expression involving the state of the calling instance, but not + * involving any parameters to the calling method. + * + * @param expression a boolean expression + * @param errorMessage the exception message to use if the check fails; will be converted to a + * string using {@link String#valueOf(Object)} + * @throws IllegalStateException if {@code expression} is false + */ + public static void checkState(boolean expression, @Nullable Object errorMessage) { + if (!expression) { + throw new IllegalStateException(String.valueOf(errorMessage)); + } + } + + /** + * Ensures the truth of an expression involving the state of the calling instance, but not + * involving any parameters to the calling method. + * + * @param expression a boolean expression + * @param errorMessageTemplate a template for the exception message should the check fail. The + * message is formed by replacing each {@code %s} placeholder in the template with an + * argument. These are matched by position - the first {@code %s} gets {@code + * errorMessageArgs[0]}, etc. Unmatched arguments will be appended to the formatted message + * in square braces. Unmatched placeholders will be left as-is. + * @param errorMessageArgs the arguments to be substituted into the message template. Arguments + * are converted to strings using {@link String#valueOf(Object)}. + * @throws IllegalStateException if {@code expression} is false + * @throws NullPointerException if the check fails and either {@code errorMessageTemplate} or + * {@code errorMessageArgs} is null (don't let this happen) + */ + public static void checkState(boolean expression, + @Nullable String errorMessageTemplate, + @Nullable Object... errorMessageArgs) { + if (!expression) { + throw new IllegalStateException(format(errorMessageTemplate, errorMessageArgs)); + } + } + + /** + * Ensures that an object reference passed as a parameter to the calling method is not null. + * + * @param reference an object reference + * @return the non-null reference that was validated + * @throws NullPointerException if {@code reference} is null + */ + public static T checkNotNull(T reference) { + if (reference == null) { + throw new NullPointerException(); + } + return reference; + } + + /** + * Ensures that an object reference passed as a parameter to the calling method is not null. + * + * @param reference an object reference + * @param errorMessage the exception message to use if the check fails; will be converted to a + * string using {@link String#valueOf(Object)} + * @return the non-null reference that was validated + * @throws NullPointerException if {@code reference} is null + */ + public static T checkNotNull(T reference, @Nullable Object errorMessage) { + if (reference == null) { + throw new NullPointerException(String.valueOf(errorMessage)); + } + return reference; + } + + /** + * Ensures that an object reference passed as a parameter to the calling method is not null. + * + * @param reference an object reference + * @param errorMessageTemplate a template for the exception message should the check fail. The + * message is formed by replacing each {@code %s} placeholder in the template with an + * argument. These are matched by position - the first {@code %s} gets {@code + * errorMessageArgs[0]}, etc. Unmatched arguments will be appended to the formatted message + * in square braces. Unmatched placeholders will be left as-is. + * @param errorMessageArgs the arguments to be substituted into the message template. Arguments + * are converted to strings using {@link String#valueOf(Object)}. + * @return the non-null reference that was validated + * @throws NullPointerException if {@code reference} is null + */ + public static T checkNotNull(T reference, + @Nullable String errorMessageTemplate, + @Nullable Object... errorMessageArgs) { + if (reference == null) { + // If either of these parameters is null, the right thing happens anyway + throw new NullPointerException(format(errorMessageTemplate, errorMessageArgs)); + } + return reference; + } + + /* + * All recent hotspots (as of 2009) *really* like to have the natural code + * + * if (guardExpression) { + * throw new BadException(messageExpression); + * } + * + * refactored so that messageExpression is moved to a separate String-returning method. + * + * if (guardExpression) { + * throw new BadException(badMsg(...)); + * } + * + * The alternative natural refactorings into void or Exception-returning methods are much slower. + * This is a big deal - we're talking factors of 2-8 in microbenchmarks, not just 10-20%. (This + * is a hotspot optimizer bug, which should be fixed, but that's a separate, big project). + * + * The coding pattern above is heavily used in java.util, e.g. in ArrayList. There is a + * RangeCheckMicroBenchmark in the JDK that was used to test this. + * + * But the methods in this class want to throw different exceptions, depending on the args, so it + * appears that this pattern is not directly applicable. But we can use the ridiculous, devious + * trick of throwing an exception in the middle of the construction of another exception. Hotspot + * is fine with that. + */ + + /** + * Ensures that {@code index} specifies a valid element in an array, list or string of size + * {@code size}. An element index may range from zero, inclusive, to {@code size}, exclusive. + * + * @param index a user-supplied index identifying an element of an array, list or string + * @param size the size of that array, list or string + * @return the value of {@code index} + * @throws IndexOutOfBoundsException if {@code index} is negative or is not less than {@code size} + * @throws IllegalArgumentException if {@code size} is negative + */ + public static int checkElementIndex(int index, int size) { + return checkElementIndex(index, size, "index"); + } + + /** + * Ensures that {@code index} specifies a valid element in an array, list or string of size + * {@code size}. An element index may range from zero, inclusive, to {@code size}, exclusive. + * + * @param index a user-supplied index identifying an element of an array, list or string + * @param size the size of that array, list or string + * @param desc the text to use to describe this index in an error message + * @return the value of {@code index} + * @throws IndexOutOfBoundsException if {@code index} is negative or is not less than {@code size} + * @throws IllegalArgumentException if {@code size} is negative + */ + public static int checkElementIndex( + int index, int size, @Nullable String desc) { + // Carefully optimized for execution by hotspot (explanatory comment above) + if (index < 0 || index >= size) { + throw new IndexOutOfBoundsException(badElementIndex(index, size, desc)); + } + return index; + } + + private static String badElementIndex(int index, int size, String desc) { + if (index < 0) { + return format("%s (%s) must not be negative", desc, index); + } else if (size < 0) { + throw new IllegalArgumentException("negative size: " + size); + } else { // index >= size + return format("%s (%s) must be less than size (%s)", desc, index, size); + } + } + + /** + * Ensures that {@code index} specifies a valid position in an array, list or string of + * size {@code size}. A position index may range from zero to {@code size}, inclusive. + * + * @param index a user-supplied index identifying a position in an array, list or string + * @param size the size of that array, list or string + * @return the value of {@code index} + * @throws IndexOutOfBoundsException if {@code index} is negative or is greater than {@code size} + * @throws IllegalArgumentException if {@code size} is negative + */ + public static int checkPositionIndex(int index, int size) { + return checkPositionIndex(index, size, "index"); + } + + /** + * Ensures that {@code index} specifies a valid position in an array, list or string of + * size {@code size}. A position index may range from zero to {@code size}, inclusive. + * + * @param index a user-supplied index identifying a position in an array, list or string + * @param size the size of that array, list or string + * @param desc the text to use to describe this index in an error message + * @return the value of {@code index} + * @throws IndexOutOfBoundsException if {@code index} is negative or is greater than {@code size} + * @throws IllegalArgumentException if {@code size} is negative + */ + public static int checkPositionIndex(int index, int size, @Nullable String desc) { + // Carefully optimized for execution by hotspot (explanatory comment above) + if (index < 0 || index > size) { + throw new IndexOutOfBoundsException(badPositionIndex(index, size, desc)); + } + return index; + } + + private static String badPositionIndex(int index, int size, String desc) { + if (index < 0) { + return format("%s (%s) must not be negative", desc, index); + } else if (size < 0) { + throw new IllegalArgumentException("negative size: " + size); + } else { // index > size + return format("%s (%s) must not be greater than size (%s)", desc, index, size); + } + } + + /** + * Ensures that {@code start} and {@code end} specify a valid positions in an array, list + * or string of size {@code size}, and are in order. A position index may range from zero to + * {@code size}, inclusive. + * + * @param start a user-supplied index identifying a starting position in an array, list or string + * @param end a user-supplied index identifying a ending position in an array, list or string + * @param size the size of that array, list or string + * @throws IndexOutOfBoundsException if either index is negative or is greater than {@code size}, + * or if {@code end} is less than {@code start} + * @throws IllegalArgumentException if {@code size} is negative + */ + public static void checkPositionIndexes(int start, int end, int size) { + // Carefully optimized for execution by hotspot (explanatory comment above) + if (start < 0 || end < start || end > size) { + throw new IndexOutOfBoundsException(badPositionIndexes(start, end, size)); + } + } + + private static String badPositionIndexes(int start, int end, int size) { + if (start < 0 || start > size) { + return badPositionIndex(start, size, "start index"); + } + if (end < 0 || end > size) { + return badPositionIndex(end, size, "end index"); + } + // end < start + return format("end index (%s) must not be less than start index (%s)", end, start); + } + + /** + * Substitutes each {@code %s} in {@code template} with an argument. These are matched by + * position: the first {@code %s} gets {@code args[0]}, etc. If there are more arguments than + * placeholders, the unmatched arguments will be appended to the end of the formatted message in + * square braces. + * + * @param template a non-null string containing 0 or more {@code %s} placeholders. + * @param args the arguments to be substituted into the message template. Arguments are converted + * to strings using {@link String#valueOf(Object)}. Arguments can be null. + */ + // Note that this is somewhat-improperly used from Verify.java as well. + static String format(String template, @Nullable Object... args) { + template = String.valueOf(template); // null -> "null" + + // start substituting the arguments into the '%s' placeholders + StringBuilder builder = new StringBuilder(template.length() + 16 * args.length); + int templateStart = 0; + int i = 0; + while (i < args.length) { + int placeholderStart = template.indexOf("%s", templateStart); + if (placeholderStart == -1) { + break; + } + builder.append(template.substring(templateStart, placeholderStart)); + builder.append(args[i++]); + templateStart = placeholderStart + 2; + } + builder.append(template.substring(templateStart)); + + // if we run out of placeholders, append the extra args in square braces + if (i < args.length) { + builder.append(" ["); + builder.append(args[i++]); + while (i < args.length) { + builder.append(", "); + builder.append(args[i++]); + } + builder.append(']'); + } + + return builder.toString(); + } +} diff --git a/.svn/pristine/81/811eab84b5842e9027e1e69bd9bbac547e97ff59.svn-base b/.svn/pristine/81/811eab84b5842e9027e1e69bd9bbac547e97ff59.svn-base new file mode 100644 index 0000000..980ebe9 --- /dev/null +++ b/.svn/pristine/81/811eab84b5842e9027e1e69bd9bbac547e97ff59.svn-base @@ -0,0 +1,3 @@ +eclipse.preferences.version=1 +encoding//src/main/resources/jPpush.properties=UTF-8 +encoding/=UTF-8 diff --git a/.svn/pristine/85/85264b821ffc1e0e18c8c8e48a2587d2c304b173.svn-base b/.svn/pristine/85/85264b821ffc1e0e18c8c8e48a2587d2c304b173.svn-base new file mode 100644 index 0000000..3810fa6 --- /dev/null +++ b/.svn/pristine/85/85264b821ffc1e0e18c8c8e48a2587d2c304b173.svn-base @@ -0,0 +1,34 @@ +package com.ifish.jpush.schedule; + +import com.google.gson.JsonObject; +import com.google.gson.annotations.Expose; +import com.ifish.jpush.common.resp.BaseResult; + +public class ScheduleResult extends BaseResult{ + + @Expose String schedule_id; + @Expose String name; + @Expose Boolean enabled; + @Expose JsonObject trigger; + @Expose JsonObject push; + + public String getSchedule_id() { + return schedule_id; + } + + public String getName() { + return name; + } + + public Boolean getEnabled() { + return enabled; + } + + public JsonObject getTrigger() { + return trigger; + } + + public JsonObject getPush() { + return push; + } +} diff --git a/.svn/pristine/87/87ab9531e1222351568346cf9057a0cae36112b8.svn-base b/.svn/pristine/87/87ab9531e1222351568346cf9057a0cae36112b8.svn-base new file mode 100644 index 0000000..3bd5d0a --- /dev/null +++ b/.svn/pristine/87/87ab9531e1222351568346cf9057a0cae36112b8.svn-base @@ -0,0 +1 @@ +org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/.svn/pristine/8a/8a46f8d0ba8e29f652cc8825ed4380d5b83f8ec8.svn-base b/.svn/pristine/8a/8a46f8d0ba8e29f652cc8825ed4380d5b83f8ec8.svn-base new file mode 100644 index 0000000..dfe1968 --- /dev/null +++ b/.svn/pristine/8a/8a46f8d0ba8e29f652cc8825ed4380d5b83f8ec8.svn-base @@ -0,0 +1,34 @@ +package com.ifish.jpush.report; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.List; + +import com.google.gson.annotations.Expose; +import com.google.gson.reflect.TypeToken; +import com.ifish.jpush.common.resp.BaseResult; +import com.ifish.jpush.common.resp.ResponseWrapper; + +public class ReceivedsResult extends BaseResult { + private static final Type RECEIVED_TYPE = new TypeToken>(){}.getType(); + + @Expose public List received_list = new ArrayList(); + + + public static class Received { + @Expose public long msg_id; + @Expose public int android_received; + @Expose public int ios_apns_sent; + } + + static ReceivedsResult fromResponse(ResponseWrapper responseWrapper) { + ReceivedsResult result = new ReceivedsResult(); + if (responseWrapper.isServerResponse()) { + result.received_list = _gson.fromJson(responseWrapper.responseContent, RECEIVED_TYPE); + } + + result.setResponseWrapper(responseWrapper); + return result; + } + +} diff --git a/.svn/pristine/8d/8d6831cafa25d963117dd7df1a406eda226e4bf4.svn-base b/.svn/pristine/8d/8d6831cafa25d963117dd7df1a406eda226e4bf4.svn-base new file mode 100644 index 0000000..4c46f36 --- /dev/null +++ b/.svn/pristine/8d/8d6831cafa25d963117dd7df1a406eda226e4bf4.svn-base @@ -0,0 +1,16 @@ +#极光推送 +#appKey +jpush.android.appKey=d970d5e193cb2a0bbe41653c +#secret +jpush.android.secret=60162c8cf195ce9f4dc76629 +#production +jpush.android.productionMode=true +#appKey +jpush.ios.appKey=d147124018074eb970474e48 +#secret +jpush.ios.secret=a7d41825e75082b13675c326 +#production +jpush.ios.productionMode=true +#云信IM +netease.appKey=87b0e3315dfc2df08060bcb54246da68 +netease.appSecret=e62f6c247b46 diff --git a/.svn/pristine/8e/8e6ddf21c656e1b7fb6016984ec6f0d65bc76eda.svn-base b/.svn/pristine/8e/8e6ddf21c656e1b7fb6016984ec6f0d65bc76eda.svn-base new file mode 100644 index 0000000..2934215 --- /dev/null +++ b/.svn/pristine/8e/8e6ddf21c656e1b7fb6016984ec6f0d65bc76eda.svn-base @@ -0,0 +1,35 @@ +package com.ifish.jpush.utils; + + +import java.text.ParseException; +import java.text.SimpleDateFormat; + +public class TimeUtils { + + private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; + private static final String TIME_ONLY_FORMAT = "HH:mm:ss"; + + + public static boolean isDateFormat(String time) { + try { + SimpleDateFormat format = new SimpleDateFormat(DATE_FORMAT); + format.setLenient(false); + format.parse(time); + } catch (ParseException e) { + return false; + } + return true; + } + + public static boolean isTimeFormat(String time) { + try{ + SimpleDateFormat format = new SimpleDateFormat(TIME_ONLY_FORMAT); + format.setLenient(false); + format.parse(time); + } catch (ParseException e) { + return false; + } + return true; + } + +} diff --git a/.svn/pristine/8f/8f6523d16c00dc8d8bd7fa2b812e6221661b460a.svn-base b/.svn/pristine/8f/8f6523d16c00dc8d8bd7fa2b812e6221661b460a.svn-base new file mode 100644 index 0000000..84adff3 --- /dev/null +++ b/.svn/pristine/8f/8f6523d16c00dc8d8bd7fa2b812e6221661b460a.svn-base @@ -0,0 +1,126 @@ +package com.ifish.jpush.report; + +import java.net.URLEncoder; +import java.util.regex.Pattern; + +import com.ifish.jpush.common.ClientConfig; +import com.ifish.jpush.common.ServiceHelper; +import com.ifish.jpush.common.TimeUnit; +import com.ifish.jpush.common.connection.HttpProxy; +import com.ifish.jpush.common.connection.IHttpClient; +import com.ifish.jpush.common.connection.NativeHttpClient; +import com.ifish.jpush.common.resp.APIConnectionException; +import com.ifish.jpush.common.resp.APIRequestException; +import com.ifish.jpush.common.resp.BaseResult; +import com.ifish.jpush.common.resp.ResponseWrapper; +import com.ifish.jpush.utils.StringUtils; + +public class ReportClient { + + private final NativeHttpClient _httpClient; + private String _hostName; + private String _receivePath; + private String _userPath; + private String _messagePath; + + public ReportClient(String masterSecret, String appKey) { + this(masterSecret, appKey, IHttpClient.DEFAULT_MAX_RETRY_TIMES, null); + } + + public ReportClient(String masterSecret, String appKey, int maxRetryTimes) { + this(masterSecret, appKey, maxRetryTimes, null); + } + + public ReportClient(String masterSecret, String appKey, int maxRetryTimes, HttpProxy proxy) { + this(masterSecret, appKey, maxRetryTimes, proxy, ClientConfig.getInstance()); + } + + public ReportClient(String masterSecret, String appKey, int maxRetryTimes, HttpProxy proxy, ClientConfig conf) { + ServiceHelper.checkBasic(appKey, masterSecret); + + _hostName = (String) conf.get(ClientConfig.REPORT_HOST_NAME); + _receivePath = (String) conf.get(ClientConfig.REPORT_RECEIVE_PATH); + _userPath = (String) conf.get(ClientConfig.REPORT_USER_PATH); + _messagePath = (String) conf.get(ClientConfig.REPORT_MESSAGE_PATH); + + String authCode = ServiceHelper.getBasicAuthorization(appKey, masterSecret); + _httpClient = new NativeHttpClient(authCode, maxRetryTimes, proxy); + } + + + public ReceivedsResult getReceiveds(String[] msgIdArray) + throws APIConnectionException, APIRequestException { + return getReceiveds(StringUtils.arrayToString(msgIdArray)); + } + + public ReceivedsResult getReceiveds(String msgIds) + throws APIConnectionException, APIRequestException { + checkMsgids(msgIds); + + String url = _hostName + _receivePath + "?msg_ids=" + msgIds; + ResponseWrapper response = _httpClient.sendGet(url); + + return ReceivedsResult.fromResponse(response); + } + + public MessagesResult getMessages(String msgIds) + throws APIConnectionException, APIRequestException { + checkMsgids(msgIds); + + String url = _hostName + _messagePath + "?msg_ids=" + msgIds; + ResponseWrapper response = _httpClient.sendGet(url); + + return MessagesResult.fromResponse(response); + } + + public UsersResult getUsers(TimeUnit timeUnit, String start, int duration) + throws APIConnectionException, APIRequestException { + String startEncoded = null; + try { + startEncoded = URLEncoder.encode(start, "utf-8"); + } catch (Exception e) { + } + + String url = _hostName + _userPath + + "?time_unit=" + timeUnit.toString() + + "&start=" + startEncoded + "&duration=" + duration; + ResponseWrapper response = _httpClient.sendGet(url); + + return BaseResult.fromResponse(response, UsersResult.class); + } + + + private final static Pattern MSGID_PATTERNS = Pattern.compile("[^0-9, ]"); + + public static void checkMsgids(String msgIds) { + if (StringUtils.isTrimedEmpty(msgIds)) { + throw new IllegalArgumentException("msgIds param is required."); + } + + if (MSGID_PATTERNS.matcher(msgIds).find()) { + throw new IllegalArgumentException("msgIds param format is incorrect. " + + "It should be msg_id (number) which response from JPush Push API. " + + "If there are many, use ',' as interval. "); + } + + msgIds = msgIds.trim(); + if (msgIds.endsWith(",")) { + msgIds = msgIds.substring(0, msgIds.length() - 1); + } + + String[] splits = msgIds.split(","); + try { + for (String s : splits) { + s = s.trim(); + if (!StringUtils.isEmpty(s)) { + Long.parseLong(s); + } + } + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Every msg_id should be valid Long number which splits by ','"); + } + } + +} + + diff --git a/.svn/pristine/90/902338f1dbb50c0f79cee5883b2858b62b172a08.svn-base b/.svn/pristine/90/902338f1dbb50c0f79cee5883b2858b62b172a08.svn-base new file mode 100644 index 0000000..63b8bff --- /dev/null +++ b/.svn/pristine/90/902338f1dbb50c0f79cee5883b2858b62b172a08.svn-base @@ -0,0 +1,89 @@ +package com.ifish.jpush.utils; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.security.MessageDigest; + + +public class StringUtils { + private final static String[] hexDigits = { "0", "1", "2", "3", "4", "5", + "6", "7", "8", "9", "A", "B", "C", "D", "E", "F" }; + + private static String byteArrayToHexString(byte[] b) { + StringBuffer resultSb = new StringBuffer(); + for (int i = 0; i < b.length; i++) { + resultSb.append(byteToHexString(b[i])); + } + return resultSb.toString(); + } + + private static String byteToHexString(byte b) { + int n = b; + if (n < 0) + n = 256 + n; + int d1 = n / 16; + int d2 = n % 16; + return hexDigits[d1] + hexDigits[d2]; + } + + public static String toMD5(String origin) { + String resultString = null; + try { + resultString = new String(origin); + MessageDigest md = MessageDigest.getInstance("MD5"); + resultString = byteArrayToHexString(md.digest(resultString.getBytes())); + } catch (Exception ex) { + ex.printStackTrace(); + } + return resultString; + } + + public static String encodeParam(String param) { + String encodeParam = null; + try { + encodeParam = URLEncoder.encode(param, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return encodeParam; + } + + public static String arrayToString(String[] values) { + if (null == values) return ""; + + StringBuffer buffer = new StringBuffer(values.length); + for (int i = 0; i < values.length; i++) { + buffer.append(values[i]).append(","); + } + if (buffer.length() > 0) { + return buffer.toString().substring(0, buffer.length() - 1); + } + return ""; + } + + public static boolean isEmpty(String s) { + return s == null || s.length() == 0; + } + + public static boolean isTrimedEmpty(String s) { + return s == null || s.trim().length() == 0; + } + + public static boolean isNotEmpty(String s) { + return s != null && s.length() > 0; + } + + public static boolean isLineBroken(String s) { + if ( null == s ) { + return false; + } + if (s.contains("\n")) { + return true; + } + if (s.contains("\r\n")) { + return true; + } + return false; + } + +} diff --git a/.svn/pristine/92/9223edd1c78f5cc0903227429457796ee91266ce.svn-base b/.svn/pristine/92/9223edd1c78f5cc0903227429457796ee91266ce.svn-base new file mode 100644 index 0000000..b9412c0 --- /dev/null +++ b/.svn/pristine/92/9223edd1c78f5cc0903227429457796ee91266ce.svn-base @@ -0,0 +1,290 @@ +package com.ifish.netease; + +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.http.HttpResponse; +import org.apache.http.NameValuePair; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.ifish.enums.NeteaseEnum; +import com.ifish.util.IfishUtil; + +public class NeteaseIM { + + String appKey = ""; + String appSecret = ""; + + private static Logger log = LoggerFactory.getLogger(NeteaseIM.class); + + public NeteaseIM(String appKey,String appSecret){ + this.appKey=appKey; + this.appSecret=appSecret; + } + /** + * 创建云信ID + * @param accid 云信ID,最大长度32字符,必须保证一个APP内唯一 + * @param name 云信ID昵称,最大长度64字符,用来PUSH推送 时显示的昵称 + * @param icon 云信ID头像URL,第三方可选填,最大长度1024 + * @param props json属性,第三方可选填,最大长度1024字符 + * @return + * @throws Exception + */ + public Map createAccid(String accid,String name,String icon,String props){ + try { + DefaultHttpClient httpClient = new DefaultHttpClient(); + String url = "https://api.netease.im/nimserver/user/create.action"; + HttpPost httpPost = new HttpPost(url); + String nonce = IfishUtil.getCharAndNumr(10); + String curTime = String.valueOf((new Date()).getTime() / 1000L); + //计算CheckSum + String checkSum = CheckSumBuilder.getCheckSum(appSecret, nonce ,curTime); + //设置请求的header + httpPost.addHeader("AppKey", appKey); + httpPost.addHeader("Nonce", nonce); + httpPost.addHeader("CurTime", curTime); + httpPost.addHeader("CheckSum", checkSum); + httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8"); + //设置请求的参数 + List nvps = new ArrayList(); + nvps.add(new BasicNameValuePair("accid", accid)); + nvps.add(new BasicNameValuePair("name", name)); + nvps.add(new BasicNameValuePair("icon", icon)); + nvps.add(new BasicNameValuePair("props", props)); + httpPost.setEntity(new UrlEncodedFormEntity(nvps, "utf-8")); + //执行请求 + HttpResponse response = httpClient.execute(httpPost); + //执行结果 + String responseStr = EntityUtils.toString(response.getEntity(), "utf-8"); + System.out.println(responseStr); + JSONObject json = new JSONObject(responseStr); + String code = json.getString("code"); + Map map = new HashMap(); + map.put("code", code); + //200 + if(code.equals(NeteaseEnum.status200.getKey())){ + JSONObject infoJson = json.getJSONObject("info"); + String token = infoJson.getString("token"); + map.put("token", token); + } + else if(code.equals(NeteaseEnum.status414.getKey())){ + String desc = json.getString("desc"); + } + return map; + } catch (Exception e) { + log.error("CreateAccid error message:{},{}",accid,e.toString()); + } + return null; + } + /** + * 云信ID基本信息更新 + * @param accid 云信ID,最大长度32字符,必须保证一个APP内唯一 + * @param token 云信ID可以指定登录token值,最大长度128字符 + * @param props json属性,第三方可选填,最大长度1024字符 + * @return + * @throws Exception + */ + public Map updateAccid(String accid,String token,String props){ + try { + DefaultHttpClient httpClient = new DefaultHttpClient(); + String url = "https://api.netease.im/nimserver/user/update.action"; + HttpPost httpPost = new HttpPost(url); + String nonce = IfishUtil.getCharAndNumr(10); + String curTime = String.valueOf((new Date()).getTime() / 1000L); + //计算CheckSum + String checkSum = CheckSumBuilder.getCheckSum(appSecret, nonce ,curTime); + //设置请求的header + httpPost.addHeader("AppKey", appKey); + httpPost.addHeader("Nonce", nonce); + httpPost.addHeader("CurTime", curTime); + httpPost.addHeader("CheckSum", checkSum); + httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8"); + //设置请求的参数 + List nvps = new ArrayList(); + nvps.add(new BasicNameValuePair("accid", accid)); + nvps.add(new BasicNameValuePair("token", token)); + nvps.add(new BasicNameValuePair("props", props)); + httpPost.setEntity(new UrlEncodedFormEntity(nvps, "utf-8")); + //执行请求 + HttpResponse response = httpClient.execute(httpPost); + //执行结果 + String responseStr = EntityUtils.toString(response.getEntity(), "utf-8"); + JSONObject json = new JSONObject(responseStr); + String code = json.getString("code"); + Map map = new HashMap(); + map.put("code", code); + return map; + } catch (Exception e) { + log.error("updateAccid error message:{},{}",accid,e.toString()); + } + return null; + } + /** + * 更新并获取新token + * @param accid + * @return + * @throws Exception + */ + public Map refreshToken(String accid){ + try { + DefaultHttpClient httpClient = new DefaultHttpClient(); + String url = "https://api.netease.im/nimserver/user/refreshToken.action"; + HttpPost httpPost = new HttpPost(url); + String nonce = IfishUtil.getCharAndNumr(10); + String curTime = String.valueOf((new Date()).getTime() / 1000L); + //计算CheckSum + String checkSum = CheckSumBuilder.getCheckSum(appSecret, nonce ,curTime); + //设置请求的header + httpPost.addHeader("AppKey", appKey); + httpPost.addHeader("Nonce", nonce); + httpPost.addHeader("CurTime", curTime); + httpPost.addHeader("CheckSum", checkSum); + httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8"); + //设置请求的参数 + List nvps = new ArrayList(); + nvps.add(new BasicNameValuePair("accid", accid)); + httpPost.setEntity(new UrlEncodedFormEntity(nvps, "utf-8")); + //执行请求 + HttpResponse response = httpClient.execute(httpPost); + //执行结果 + String responseStr = EntityUtils.toString(response.getEntity(), "utf-8"); + JSONObject json = new JSONObject(responseStr); + String code = json.getString("code"); + Map map = new HashMap(); + map.put("code", code); + //200 + if(code.equals(NeteaseEnum.status200.getKey())){ + JSONObject infoJson = json.getJSONObject("info"); + String token = infoJson.getString("token"); + map.put("token", token); + } + else if(code.equals(NeteaseEnum.status414.getKey())){ + String desc = json.getString("desc"); + } + return map; + } catch (Exception e) { + log.error("refreshToken error message:{},{}",accid,e.toString()); + } + return null; + } + + /** + * 发送普通消息 + * @param from + * @param to + * @param msg + * @return + */ + public Map sendMsg(String from,String to,String msg){ + try { + DefaultHttpClient httpClient = new DefaultHttpClient(); + String url = "https://api.netease.im/nimserver/msg/sendMsg.action"; + HttpPost httpPost = new HttpPost(url); + String nonce = IfishUtil.getCharAndNumr(10); + String curTime = String.valueOf((new Date()).getTime() / 1000L); + //计算CheckSum + String checkSum = CheckSumBuilder.getCheckSum(appSecret, nonce ,curTime); + //设置请求的header + httpPost.addHeader("AppKey", appKey); + httpPost.addHeader("Nonce", nonce); + httpPost.addHeader("CurTime", curTime); + httpPost.addHeader("CheckSum", checkSum); + httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8"); + //设置请求的参数 + List nvps = new ArrayList(); + nvps.add(new BasicNameValuePair("from", from)); + nvps.add(new BasicNameValuePair("to", to)); + nvps.add(new BasicNameValuePair("ope", "0")); + nvps.add(new BasicNameValuePair("type", "0")); + nvps.add(new BasicNameValuePair("body", "{\"msg\":\""+msg+"\"}")); + httpPost.setEntity(new UrlEncodedFormEntity(nvps, "utf-8")); + //执行请求 + HttpResponse response = httpClient.execute(httpPost); + //执行结果 + String responseStr = EntityUtils.toString(response.getEntity(), "utf-8"); + System.out.println(responseStr); + JSONObject json = new JSONObject(responseStr); + String code = json.getString("code"); + Map map = new HashMap(); + map.put("code", code); + //200 + if(code.equals(NeteaseEnum.status200.getKey())){ + + } + else if(code.equals(NeteaseEnum.status414.getKey())){ + String desc = json.getString("desc"); + } + return map; + } catch (Exception e) { + log.error("refreshToken error message:{}",e.toString()); + } + return null; + } + /** + * 批量发送点对点普通消息 + * @param fromAccid + * @param toAccids + * @param msg + * @return + */ + public Map sendBatchMsg(String fromAccid,String toAccids,String msg){ + try { + DefaultHttpClient httpClient = new DefaultHttpClient(); + String url = "https://api.netease.im/nimserver/msg/sendBatchMsg.action"; + HttpPost httpPost = new HttpPost(url); + String nonce = IfishUtil.getCharAndNumr(10); + String curTime = String.valueOf((new Date()).getTime() / 1000L); + //计算CheckSum + String checkSum = CheckSumBuilder.getCheckSum(appSecret, nonce ,curTime); + //设置请求的header + httpPost.addHeader("AppKey", appKey); + httpPost.addHeader("Nonce", nonce); + httpPost.addHeader("CurTime", curTime); + httpPost.addHeader("CheckSum", checkSum); + httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8"); + //设置请求的参数 + List nvps = new ArrayList(); + nvps.add(new BasicNameValuePair("fromAccid", fromAccid)); + nvps.add(new BasicNameValuePair("toAccids", toAccids)); + nvps.add(new BasicNameValuePair("type", "0")); + nvps.add(new BasicNameValuePair("body", "{\"msg\":\""+msg+"\"}")); + httpPost.setEntity(new UrlEncodedFormEntity(nvps, "utf-8")); + //执行请求 + HttpResponse response = httpClient.execute(httpPost); + //执行结果 + String responseStr = EntityUtils.toString(response.getEntity(), "utf-8"); + System.out.println(responseStr); + JSONObject json = new JSONObject(responseStr); + String code = json.getString("code"); + Map map = new HashMap(); + map.put("code", code); + //200 + if(code.equals(NeteaseEnum.status200.getKey())){ + + } + else if(code.equals(NeteaseEnum.status414.getKey())){ + String desc = json.getString("desc"); + } + return map; + } catch (Exception e) { + log.error("refreshToken error message:{}",e.toString()); + } + return null; + } + public static void main(String[] args) { + List list= new ArrayList(); + list.add("hello"); + list.add("hello1"); + new NeteaseIM("87b0e3315dfc2df08060bcb54246da68", "e62f6c247b46").createAccid("ifish", "爱鱼奇", "", ""); + } +} diff --git a/.svn/pristine/94/9448515cbe4935fa91f39fbc832338ed5d8eac2c.svn-base b/.svn/pristine/94/9448515cbe4935fa91f39fbc832338ed5d8eac2c.svn-base new file mode 100644 index 0000000..226a872 --- /dev/null +++ b/.svn/pristine/94/9448515cbe4935fa91f39fbc832338ed5d8eac2c.svn-base @@ -0,0 +1,17 @@ +package com.ifish.jpush.common.resp; + +public class DefaultResult extends BaseResult { + + public static DefaultResult fromResponse(ResponseWrapper responseWrapper) { + DefaultResult result = null; + + if (responseWrapper.isServerResponse()) { + result = new DefaultResult(); + } + if(result!=null){ + result.setResponseWrapper(responseWrapper); + } + return result; + } + +} diff --git a/.svn/pristine/95/95fb12ff3801f3b49296d6141140a0100943ad26.svn-base b/.svn/pristine/95/95fb12ff3801f3b49296d6141140a0100943ad26.svn-base new file mode 100644 index 0000000..abc37db --- /dev/null +++ b/.svn/pristine/95/95fb12ff3801f3b49296d6141140a0100943ad26.svn-base @@ -0,0 +1,11 @@ +package com.ifish.jpush.push.model; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; + +public interface PushModel { + + public static Gson gson = new Gson(); + public JsonElement toJSON(); + +} diff --git a/.svn/pristine/99/991cbb72d18bc0c247162288f2252af39ce79d64.svn-base b/.svn/pristine/99/991cbb72d18bc0c247162288f2252af39ce79d64.svn-base new file mode 100644 index 0000000..6b5aebc --- /dev/null +++ b/.svn/pristine/99/991cbb72d18bc0c247162288f2252af39ce79d64.svn-base @@ -0,0 +1,13 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.7 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.source=1.7 diff --git a/.svn/pristine/9c/9c6761fb524730184dcea7c0adfd5da1cad12852.svn-base b/.svn/pristine/9c/9c6761fb524730184dcea7c0adfd5da1cad12852.svn-base new file mode 100644 index 0000000..58a425c --- /dev/null +++ b/.svn/pristine/9c/9c6761fb524730184dcea7c0adfd5da1cad12852.svn-base @@ -0,0 +1,93 @@ +package com.ifish.jpush.common.resp; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +public abstract class BaseResult implements IRateLimiting { + public static final int ERROR_CODE_NONE = -1; + public static final int ERROR_CODE_OK = 0; + public static final String ERROR_MESSAGE_NONE = "None error message."; + + protected static final int RESPONSE_OK = 200; + protected static Gson _gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create(); + + private ResponseWrapper responseWrapper; + + public void setResponseWrapper(ResponseWrapper responseWrapper) { + this.responseWrapper = responseWrapper; + } + + public String getOriginalContent() { + if (null != responseWrapper) { + return responseWrapper.responseContent; + } + return null; + } + + public int getResponseCode() { + if(null != responseWrapper) { + return responseWrapper.responseCode; + } + return -1; + } + + public boolean isResultOK() { + if(null != responseWrapper) { + return ( responseWrapper.responseCode / 200 ) == 1; + } + return false; + } + + public static T fromResponse( + ResponseWrapper responseWrapper, Class clazz) { + T result = null; + + if (responseWrapper.isServerResponse()) { + result = _gson.fromJson(responseWrapper.responseContent, clazz); + } else { + try { + result = clazz.newInstance(); + } catch (InstantiationException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + if(result!=null){ + result.setResponseWrapper(responseWrapper); + } + return result; + } + + + @Override + public int getRateLimitQuota() { + if (null != responseWrapper) { + return responseWrapper.rateLimitQuota; + } + return 0; + } + + @Override + public int getRateLimitRemaining() { + if (null != responseWrapper) { + return responseWrapper.rateLimitRemaining; + } + return 0; + } + + @Override + public int getRateLimitReset() { + if (null != responseWrapper) { + return responseWrapper.rateLimitReset; + } + return 0; + } + + @Override + public String toString() { + return _gson.toJson(this); + } + + +} diff --git a/.svn/pristine/9c/9cb3803e02aaecf5ce52a2922f46b8d0c7fe5943.svn-base b/.svn/pristine/9c/9cb3803e02aaecf5ce52a2922f46b8d0c7fe5943.svn-base new file mode 100644 index 0000000..70de5e6 --- /dev/null +++ b/.svn/pristine/9c/9cb3803e02aaecf5ce52a2922f46b8d0c7fe5943.svn-base @@ -0,0 +1,204 @@ +package com.ifish.jpush.examples; + +import java.util.HashMap; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.JsonObject; +import com.ifish.jpush.JPushClient; +import com.ifish.jpush.common.ClientConfig; +import com.ifish.jpush.common.resp.APIConnectionException; +import com.ifish.jpush.common.resp.APIRequestException; +import com.ifish.jpush.push.PushResult; +import com.ifish.jpush.push.model.Message; +import com.ifish.jpush.push.model.Options; +import com.ifish.jpush.push.model.Platform; +import com.ifish.jpush.push.model.PushPayload; +import com.ifish.jpush.push.model.audience.Audience; +import com.ifish.jpush.push.model.audience.AudienceTarget; +import com.ifish.jpush.push.model.notification.AndroidNotification; +import com.ifish.jpush.push.model.notification.IosNotification; +import com.ifish.jpush.push.model.notification.Notification; + +public class PushExample { + protected static final Logger LOG = LoggerFactory.getLogger(PushExample.class); + + // demo App defined in resources/jpush-api.conf + private static final String appKey ="d970d5e193cb2a0bbe41653c"; + private static final String masterSecret = "60162c8cf195ce9f4dc76629"; + + public static final String TITLE = "Test from API example"; + public static final String ALERT = "Test from API Example - alert"; + public static final String MSG_CONTENT = "Test from API Example - msgContent"; + public static final String REGISTRATION_ID = "0900e8d85ef"; + public static final String TAG = "tag_api"; + + public static void main(String[] args) { + //testSendPushWithCustomConfig(); + Map map = new HashMap(); + map.put("device_id", "1"); + map.put("device_name", "设备1"); + map.put("msg_type", "remove_device"); + testSendIosAlert("300","设备解除绑定", "你已失去对“设备1”设备的控制权", map); + //testSendAndroidNotification("40","标题401","内容40",map); + //testSendAndroidNotification("40","标题","内容"); + } + + + public static void testSendPush() { + // HttpProxy proxy = new HttpProxy("localhost", 3128); + // Can use this https proxy: https://github.com/Exa-Networks/exaproxy + JPushClient jpushClient = new JPushClient(masterSecret, appKey, 3); + + // For push, all you need do is to build PushPayload object. + PushPayload payload = buildPushObject_all_all_alert(); + + try { + PushResult result = jpushClient.sendPush(payload); + LOG.info("Got result - " + result); + + } catch (APIConnectionException e) { + LOG.error("Connection error. Should retry later. ", e); + + } catch (APIRequestException e) { + LOG.error("Error response from JPush server. Should review and fix it. ", e); + LOG.info("HTTP Status: " + e.getStatus()); + LOG.info("Error Code: " + e.getErrorCode()); + LOG.info("Error Message: " + e.getErrorMessage()); + LOG.info("Msg ID: " + e.getMsgId()); + } + } + + public static PushPayload buildPushObject_all_all_alert() { + return PushPayload.alertAll(ALERT); + } + + public static PushPayload buildPushObject_all_alias_alert() { + return PushPayload.newBuilder() + .setPlatform(Platform.all()) + .setAudience(Audience.alias("alias1")) + .setNotification(Notification.alert(ALERT)) + .build(); + } + + public static PushPayload buildPushObject_android_tag_alertWithTitle() { + return PushPayload.newBuilder() + .setPlatform(Platform.android()) + .setAudience(Audience.tag("tag1")) + .setNotification(Notification.android(ALERT, TITLE, null)) + .build(); + } + + public static PushPayload buildPushObject_android_and_ios() { + return PushPayload.newBuilder() + .setPlatform(Platform.android_ios()) + .setAudience(Audience.tag("tag1")) + .setNotification(Notification.newBuilder() + .setAlert("alert content") + .addPlatformNotification(AndroidNotification.newBuilder() + .setTitle("Android Title").build()) + .addPlatformNotification(IosNotification.newBuilder() + .incrBadge(1) + .addExtra("extra_key", "extra_value").build()) + .build()) + .build(); + } + + public static PushPayload buildPushObject_ios_tagAnd_alertWithExtrasAndMessage() { + return PushPayload.newBuilder() + .setPlatform(Platform.ios()) + .setAudience(Audience.tag_and("tag1", "tag_all")) + .setNotification(Notification.newBuilder() + .addPlatformNotification(IosNotification.newBuilder() + .setAlert(ALERT) + .setBadge(5) + .setSound("happy") + .addExtra("from", "JPush") + .build()) + .build()) + .setMessage(Message.content(MSG_CONTENT)) + .setOptions(Options.newBuilder() + .setApnsProduction(true) + .build()) + .build(); + } + + public static PushPayload buildPushObject_ios_audienceMore_messageWithExtras() { + return PushPayload.newBuilder() + .setPlatform(Platform.android_ios()) + .setAudience(Audience.newBuilder() + .addAudienceTarget(AudienceTarget.tag("tag1", "tag2")) + .addAudienceTarget(AudienceTarget.alias("alias1", "alias2")) + .build()) + .setMessage(Message.newBuilder() + .setMsgContent(MSG_CONTENT) + .addExtra("from", "JPush") + .build()) + .build(); + } + + public static void testSendPushWithCustomConfig() { + ClientConfig config = ClientConfig.getInstance(); + // Setup the custom hostname + config.setPushHostName("https://api.jpush.cn"); + + JPushClient jpushClient = new JPushClient(masterSecret, appKey, 3, null, config); + + // For push, all you need do is to build PushPayload object. + PushPayload payload = buildPushObject_all_all_alert(); + + try { + PushResult result = jpushClient.sendPush(payload); + LOG.info("Got result - " + result); + + } catch (APIConnectionException e) { + LOG.error("Connection error. Should retry later. ", e); + + } catch (APIRequestException e) { + LOG.error("Error response from JPush server. Should review and fix it. ", e); + LOG.info("HTTP Status: " + e.getStatus()); + LOG.info("Error Code: " + e.getErrorCode()); + LOG.info("Error Message: " + e.getErrorMessage()); + LOG.info("Msg ID: " + e.getMsgId()); + } + } + + public static void testSendIosAlert(String alias,String title,String body,Map extras) { + JPushClient jpushClient = new JPushClient(masterSecret, appKey, true ,86400); + try { + JsonObject json = new JsonObject(); + json.addProperty("title", title); + json.addProperty("body", body); + PushResult result = jpushClient.sendIosNotificationWithAlias(json, extras, alias); + System.out.println("Got result - " + result); + } catch (APIConnectionException e) { + LOG.error("Connection error. Should retry later. ", e); + } catch (APIRequestException e) { + LOG.error("Error response from JPush server. Should review and fix it. "+e); + LOG.error("HTTP Status: " + e.getStatus()); + LOG.error("Error Code: " + e.getErrorCode()); + System.out.println(e.getErrorCode()); + LOG.error("Error Message: " + e.getErrorMessage()); + } + } + + public static void testSendAndroidNotification(String alias,String title,String alert,Map map) { + JPushClient jpushClient = new JPushClient(masterSecret, appKey , true ,86400); + try { + PushResult result = jpushClient.sendAndroidNotificationWithAlias(title ,alert, map, alias); + System.out.println("Got result - " + result); + } catch (APIConnectionException e) { + LOG.error("Connection error. Should retry later. ", e); + } catch (APIRequestException e) { + LOG.error("Error response from JPush server. Should review and fix it. "+e); + LOG.error("HTTP Status: " + e.getStatus()); + LOG.error("Error Code: " + e.getErrorCode()); + System.out.println(e.getMessage()); + LOG.error("Error Message: " + e.getErrorMessage()); + } + } + +} + diff --git a/.svn/pristine/a1/a112be21c325d37ebc17baafd40c0386b5d09df1.svn-base b/.svn/pristine/a1/a112be21c325d37ebc17baafd40c0386b5d09df1.svn-base new file mode 100644 index 0000000..f897a7f --- /dev/null +++ b/.svn/pristine/a1/a112be21c325d37ebc17baafd40c0386b5d09df1.svn-base @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/.svn/pristine/a1/a159236f78915408fd99a618a299000657fd2c8d.svn-base b/.svn/pristine/a1/a159236f78915408fd99a618a299000657fd2c8d.svn-base new file mode 100644 index 0000000..bf44638 --- /dev/null +++ b/.svn/pristine/a1/a159236f78915408fd99a618a299000657fd2c8d.svn-base @@ -0,0 +1,163 @@ +package com.ifish.jpush.push.model.notification; + +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import com.ifish.jpush.push.model.PushModel; +import com.ifish.jpush.utils.Preconditions; + +public class Notification implements PushModel { + private final Object alert; + private final Set notifications; + + private Notification(Object alert, Set notifications) { + this.alert = alert; + this.notifications = notifications; + } + + public static Builder newBuilder() { + return new Builder(); + } + + /** + * Quick set all platform alert. + * Platform notification can override this alert. + * + * @param alert Notification alert + * @return first level notification object + */ + public static Notification alert(Object alert) { + return newBuilder().setAlert(alert).build(); + } + + /** + * shortcut + */ + public static Notification android(String alert, String title, Map extras) { + return newBuilder() + .addPlatformNotification(AndroidNotification.newBuilder() + .setAlert(alert) + .setTitle(title) + .setBuilderId(1) + .addExtras(extras) + .build()) + .build(); + } + + /** + * shortcut + */ + public static Notification ios(Object alert, Map extras) { + return newBuilder() + .addPlatformNotification(IosNotification.newBuilder() + .setAlert(alert) + .setSound("default") + .setCategory("INVITE_CATEGORY") + .addExtras(extras) + .build()) + .build(); + } + + /** + * shortcut + */ + public static Notification ios_auto_badge() { + return newBuilder() + .addPlatformNotification(IosNotification.newBuilder() + .setAlert("") + .autoBadge() + .build()) + .build(); + } + + /** + * shortcut + */ + public static Notification ios_set_badge(int badge) { + return newBuilder() + .addPlatformNotification(IosNotification.newBuilder() + .setAlert("") + .setBadge(badge) + .build()) + .build(); + } + + /** + * shortcut + */ + public static Notification ios_incr_badge(int badge) { + return newBuilder() + .addPlatformNotification(IosNotification.newBuilder() + .setAlert("") + .incrBadge(badge) + .build()) + .build(); + } + + /** + * shortcut + */ + public static Notification winphone(String alert, Map extras) { + return newBuilder() + .addPlatformNotification(WinphoneNotification.newBuilder() + .setAlert(alert) + .addExtras(extras) + .build()) + .build(); + } + + public JsonElement toJSON() { + JsonObject json = new JsonObject(); + if (null != alert) { + if(alert instanceof JsonObject) { + json.add(PlatformNotification.ALERT, (JsonObject) alert); + } else if (alert instanceof IosAlert) { + json.add(PlatformNotification.ALERT, ((IosAlert) alert).toJSON()); + } else { + json.add(PlatformNotification.ALERT, new JsonPrimitive(alert.toString())); + } + } + if (null != notifications) { + for (PlatformNotification pn : notifications) { + if (this.alert != null && pn.getAlert() == null) { + pn.setAlert(this.alert); + } + + Preconditions.checkArgument(! (null == pn.getAlert()), + "For any platform notification, alert field is needed. It can be empty string."); + + json.add(pn.getPlatform(), pn.toJSON()); + } + } + return json; + } + + public static class Builder { + private Object alert; + private Set builder; + + public Builder setAlert(Object alert) { + this.alert = alert; + return this; + } + + public Builder addPlatformNotification(PlatformNotification notification) { + if (null == builder) { + builder = new HashSet(); + } + builder.add(notification); + return this; + } + + public Notification build() { + Preconditions.checkArgument(! (null == builder && null == alert), + "No notification payload is set."); + return new Notification(alert, builder); + } + } +} + diff --git a/.svn/pristine/aa/aa268d45232b073aeb1fa3778addf777ec53e566.svn-base b/.svn/pristine/aa/aa268d45232b073aeb1fa3778addf777ec53e566.svn-base new file mode 100644 index 0000000..15f0aee --- /dev/null +++ b/.svn/pristine/aa/aa268d45232b073aeb1fa3778addf777ec53e566.svn-base @@ -0,0 +1,331 @@ +package com.ifish.jpush.common.connection; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.Authenticator; +import java.net.HttpURLConnection; +import java.net.PasswordAuthentication; +import java.net.SocketTimeoutException; +import java.net.URL; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSession; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.ifish.jpush.common.resp.APIConnectionException; +import com.ifish.jpush.common.resp.APIRequestException; +import com.ifish.jpush.common.resp.ResponseWrapper; + +/** + * The implementation has no connection pool mechanism, used origin java connection. + * + * 本实现没有连接池机制,基于 Java 原始的 HTTP 连接实现。 + * + * 遇到连接超时,会自动重连指定的次数(默认为 3);如果是读取超时,则不会自动重连。 + * + * 可选支持 HTTP 代理,同时支持 2 种方式:1) HTTP 头上加上 Proxy-Authorization 信息;2)全局配置 Authenticator.setDefault; + */ +public class NativeHttpClient implements IHttpClient { + private static final Logger LOG = LoggerFactory.getLogger(NativeHttpClient.class); + private static final String KEYWORDS_CONNECT_TIMED_OUT = "connect timed out"; + private static final String KEYWORDS_READ_TIMED_OUT = "Read timed out"; + + private int _maxRetryTimes = 0; + private String _authCode; + private HttpProxy _proxy; + + /** + * 默认的重连次数是 3 + */ + public NativeHttpClient(String authCode) { + this(authCode, DEFAULT_MAX_RETRY_TIMES, null); + } + + public NativeHttpClient(String authCode, int maxRetryTimes, HttpProxy proxy) { + this._maxRetryTimes = maxRetryTimes; + LOG.info("Created instance with _maxRetryTimes = " + _maxRetryTimes); + + this._authCode = authCode; + this._proxy = proxy; + + if ( null != _proxy && _proxy.isAuthenticationNeeded()) { + Authenticator.setDefault(new SimpleProxyAuthenticator( + _proxy.getUsername(), _proxy.getPassword())); + } + + initSSL(); + } + + public ResponseWrapper sendGet(String url) + throws APIConnectionException, APIRequestException { + return sendGet(url, null); + } + + public ResponseWrapper sendGet(String url, String content) + throws APIConnectionException, APIRequestException { + return doRequest(url, content, RequestMethod.GET); + } + + public ResponseWrapper sendDelete(String url) + throws APIConnectionException, APIRequestException { + return sendDelete(url, null); + } + + public ResponseWrapper sendDelete(String url, String content) + throws APIConnectionException, APIRequestException { + return doRequest(url, content, RequestMethod.DELETE); + } + + public ResponseWrapper sendPost(String url, String content) + throws APIConnectionException, APIRequestException { + return doRequest(url, content, RequestMethod.POST); + } + + public ResponseWrapper sendPut(String url, String content) + throws APIConnectionException, APIRequestException { + return doRequest(url, content, RequestMethod.PUT); + } + + public ResponseWrapper doRequest(String url, String content, + RequestMethod method) throws APIConnectionException, APIRequestException { + ResponseWrapper response = null; + for (int retryTimes = 0; ; retryTimes++) { + try { + response = _doRequest(url, content, method); + break; + } catch (SocketTimeoutException e) { + if (KEYWORDS_READ_TIMED_OUT.equals(e.getMessage())) { + // Read timed out. For push, maybe should not re-send. + throw new APIConnectionException(READ_TIMED_OUT_MESSAGE, e, true); + } else { // connect timed out + if (retryTimes >= _maxRetryTimes) { + throw new APIConnectionException(CONNECT_TIMED_OUT_MESSAGE, e, retryTimes); + } else { + LOG.debug("connect timed out - retry again - " + (retryTimes + 1)); + } + } + } + } + return response; + } + + private ResponseWrapper _doRequest(String url, String content, + RequestMethod method) throws APIConnectionException, APIRequestException, + SocketTimeoutException { + + LOG.debug("Send request - " + method.toString() + " "+ url); + if (null != content) { + LOG.debug("Request Content - " + content); + } + HttpURLConnection conn = null; + OutputStream out = null; + StringBuffer sb = new StringBuffer(); + ResponseWrapper wrapper = new ResponseWrapper(); + + try { + URL aUrl = new URL(url); + + if (null != _proxy) { + conn = (HttpURLConnection) aUrl.openConnection(_proxy.getNetProxy()); + if (_proxy.isAuthenticationNeeded()) { + conn.setRequestProperty("Proxy-Authorization", _proxy.getProxyAuthorization()); + } + } else { + conn = (HttpURLConnection) aUrl.openConnection(); + } + + conn.setConnectTimeout(DEFAULT_CONNECTION_TIMEOUT); + conn.setReadTimeout(DEFAULT_READ_TIMEOUT); + conn.setUseCaches(false); + conn.setRequestMethod(method.name()); + conn.setRequestProperty("User-Agent", JPUSH_USER_AGENT); + conn.setRequestProperty("Connection", "Keep-Alive"); + conn.setRequestProperty("Accept-Charset", CHARSET); + conn.setRequestProperty("Charset", CHARSET); + conn.setRequestProperty("Authorization", _authCode); + conn.setRequestProperty("Content-Type", CONTENT_TYPE_JSON); + + if(null == content) { + conn.setDoOutput(false); + } else { + conn.setDoOutput(true); + byte[] data = content.getBytes(CHARSET); + conn.setRequestProperty("Content-Length", String.valueOf(data.length)); + out = conn.getOutputStream(); + out.write(data); + out.flush(); + } + + int status = conn.getResponseCode(); + InputStream in = null; + if (status / 100 == 2) { + in = conn.getInputStream(); + } else { + in = conn.getErrorStream(); + } + + if (null != in) { + InputStreamReader reader = new InputStreamReader(in, CHARSET); + char[] buff = new char[1024]; + int len; + while ((len = reader.read(buff)) > 0) { + sb.append(buff, 0, len); + } + } + + String responseContent = sb.toString(); + wrapper.responseCode = status; + wrapper.responseContent = responseContent; + + String quota = conn.getHeaderField(RATE_LIMIT_QUOTA); + String remaining = conn.getHeaderField(RATE_LIMIT_Remaining); + String reset = conn.getHeaderField(RATE_LIMIT_Reset); + wrapper.setRateLimit(quota, remaining, reset); + + if (status >= 200 && status < 300) { + LOG.debug("Succeed to get response OK - responseCode:" + status); + LOG.debug("Response Content - " + responseContent); + + } else if (status >= 300 && status < 400) { + LOG.warn("Normal response but unexpected - responseCode:" + status + ", responseContent:" + responseContent); + + } else { + LOG.warn("Got error response - responseCode:" + status + ", responseContent:" + responseContent); + + switch (status) { + case 400: + LOG.error("Your request params is invalid. Please check them according to error message."); + wrapper.setErrorObject(); + break; + case 401: + LOG.error("Authentication failed! Please check authentication params according to docs."); + wrapper.setErrorObject(); + break; + case 403: + LOG.error("Request is forbidden! Maybe your appkey is listed in blacklist or your params is invalid."); + wrapper.setErrorObject(); + break; + case 404: + LOG.error("Request page is not found! Maybe your params is invalid."); + wrapper.setErrorObject(); + break; + case 410: + LOG.error("Request resource is no longer in service. Please according to notice on official website."); + wrapper.setErrorObject(); + case 429: + LOG.error("Too many requests! Please review your appkey's request quota."); + wrapper.setErrorObject(); + break; + case 500: + case 502: + case 503: + case 504: + LOG.error("Seems encountered server error. Maybe JPush is in maintenance? Please retry later."); + break; + default: + LOG.error("Unexpected response."); + } + + throw new APIRequestException(wrapper); + } + + } catch (SocketTimeoutException e) { + if (e.getMessage().contains(KEYWORDS_CONNECT_TIMED_OUT)) { + throw e; + } else if (e.getMessage().contains(KEYWORDS_READ_TIMED_OUT)) { + throw new SocketTimeoutException(KEYWORDS_READ_TIMED_OUT); + } + LOG.debug(IO_ERROR_MESSAGE, e); + throw new APIConnectionException(IO_ERROR_MESSAGE, e); + + } catch (IOException e) { + LOG.debug(IO_ERROR_MESSAGE, e); + throw new APIConnectionException(IO_ERROR_MESSAGE, e); + + } finally { + if (null != out) { + try { + out.close(); + } catch (IOException e) { + LOG.error("Failed to close stream.", e); + } + } + if (null != conn) { + conn.disconnect(); + } + } + + return wrapper; + } + + protected void initSSL() { + TrustManager[] tmCerts = new javax.net.ssl.TrustManager[1]; + tmCerts[0] = new SimpleTrustManager(); + try { + SSLContext sslContext = SSLContext.getInstance("SSL"); + sslContext.init(null, tmCerts, null); + HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory()); + + HostnameVerifier hostnameVerifier = new SimpleHostnameVerifier(); + HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier); + } catch (Exception e) { + LOG.error("Init SSL error", e); + } + } + + + private static class SimpleHostnameVerifier implements HostnameVerifier { + + @Override + public boolean verify(String hostname, SSLSession session) { + return true; + } + + } + + private static class SimpleTrustManager implements TrustManager, X509TrustManager { + + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) + throws CertificateException { + return; + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) + throws CertificateException { + return; + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return null; + } + } + + private static class SimpleProxyAuthenticator extends java.net.Authenticator { + private String username; + private String password; + + public SimpleProxyAuthenticator(String username, String password) { + this.username = username; + this.password = password; + } + + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication( + this.username, + this.password.toCharArray()); + } + } +} diff --git a/.svn/pristine/ad/ad4a453d3f25c885d477bee96c2c72748db1b12c.svn-base b/.svn/pristine/ad/ad4a453d3f25c885d477bee96c2c72748db1b12c.svn-base new file mode 100644 index 0000000..50e7352 --- /dev/null +++ b/.svn/pristine/ad/ad4a453d3f25c885d477bee96c2c72748db1b12c.svn-base @@ -0,0 +1,7 @@ + + + + + + + diff --git a/.svn/pristine/ae/ae2895863af03cacfa731223e977c6828dd17104.svn-base b/.svn/pristine/ae/ae2895863af03cacfa731223e977c6828dd17104.svn-base new file mode 100644 index 0000000..05335b9 --- /dev/null +++ b/.svn/pristine/ae/ae2895863af03cacfa731223e977c6828dd17104.svn-base @@ -0,0 +1,153 @@ +package com.ifish.jpush.push.model; + +import java.util.HashMap; +import java.util.Map; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import com.ifish.jpush.utils.Preconditions; + +public class Message implements PushModel { + private static final String TITLE = "title"; + private static final String MSG_CONTENT = "msg_content"; + private static final String CONTENT_TYPE = "content_type"; + private static final String EXTRAS = "extras"; + + private final String title; + private final String msgContent; + private final String contentType; + private final Map extras; + private final Map numberExtras; + private final Map booleanExtras; + + private Message(String title, String msgContent, String contentType, + Map extras, + Map numberExtras, + Map booleanExtras) { + this.title = title; + this.msgContent = msgContent; + this.contentType = contentType; + this.extras = extras; + this.numberExtras = numberExtras; + this.booleanExtras = booleanExtras; + } + + public static Builder newBuilder() { + return new Builder(); + } + + public static Message content(String msgContent) { + return new Builder().setMsgContent(msgContent).build(); + } + + @Override + public JsonElement toJSON() { + JsonObject json = new JsonObject(); + if (null != title) { + json.add(TITLE, new JsonPrimitive(title)); + } + if (null != msgContent) { + json.add(MSG_CONTENT, new JsonPrimitive(msgContent)); + } + if (null != contentType) { + json.add(CONTENT_TYPE, new JsonPrimitive(contentType)); + } + + JsonObject extrasObject = null; + if (null != extras || null != numberExtras || null != booleanExtras) { + extrasObject = new JsonObject(); + } + + if (null != extras) { + for (String key : extras.keySet()) { + extrasObject.add(key, new JsonPrimitive(extras.get(key))); + } + } + if (null != numberExtras) { + for (String key : numberExtras.keySet()) { + extrasObject.add(key, new JsonPrimitive(numberExtras.get(key))); + } + } + if (null != booleanExtras) { + for (String key : booleanExtras.keySet()) { + extrasObject.add(key, new JsonPrimitive(booleanExtras.get(key))); + } + } + + if (null != extras || null != numberExtras || null != booleanExtras) { + json.add(EXTRAS, extrasObject); + } + + return json; + } + + public static class Builder { + private String title; + private String msgContent; + private String contentType; + private Map extrasBuilder; + private Map numberExtrasBuilder; + private Map booleanExtrasBuilder; + + public Builder setTitle(String title) { + this.title = title; + return this; + } + + public Builder setMsgContent(String msgContent) { + this.msgContent = msgContent; + return this; + } + + public Builder setContentType(String contentType) { + this.contentType = contentType; + return this; + } + + public Builder addExtra(String key, String value) { + Preconditions.checkArgument(! (null == key || null == value), "Key/Value should not be null."); + if (null == extrasBuilder) { + extrasBuilder = new HashMap(); + } + extrasBuilder.put(key, value); + return this; + } + + public Builder addExtras(Map extras) { + Preconditions.checkArgument(! (null == extras), "extras should not be null."); + if (null == extrasBuilder) { + extrasBuilder = new HashMap(); + } + for (String key : extras.keySet()) { + extrasBuilder.put(key, extras.get(key)); + } + return this; + } + + public Builder addExtra(String key, Number value) { + Preconditions.checkArgument(! (null == key || null == value), "Key/Value should not be null."); + if (null == numberExtrasBuilder) { + numberExtrasBuilder = new HashMap(); + } + numberExtrasBuilder.put(key, value); + return this; + } + + public Builder addExtra(String key, Boolean value) { + Preconditions.checkArgument(! (null == key || null == value), "Key/Value should not be null."); + if (null == booleanExtrasBuilder) { + booleanExtrasBuilder = new HashMap(); + } + booleanExtrasBuilder.put(key, value); + return this; + } + + public Message build() { + Preconditions.checkArgument(! (null == msgContent), + "msgContent should be set"); + return new Message(title, msgContent, contentType, + extrasBuilder, numberExtrasBuilder, booleanExtrasBuilder); + } + } +} diff --git a/.svn/pristine/af/afd98b4d7befb8975ddca106ff887710597c159d.svn-base b/.svn/pristine/af/afd98b4d7befb8975ddca106ff887710597c159d.svn-base new file mode 100644 index 0000000..dc68569 --- /dev/null +++ b/.svn/pristine/af/afd98b4d7befb8975ddca106ff887710597c159d.svn-base @@ -0,0 +1,170 @@ +package com.ifish.job; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import net.sf.json.JSONArray; + +import org.springframework.beans.factory.annotation.Autowired; + +import com.ifish.enums.PhoneTypeEnum; +import com.ifish.jpush.JPushNotification; +import com.ifish.netease.NeteaseIM; +import com.ifish.util.IfishUtil; + +public class job{ + @Autowired + private NeteaseIM neteaseIM; + @Autowired + private JPushNotification jPushNotification2; + + private Connection connection = null; + private Statement stmt = null; + private PreparedStatement prest = null; + + /** + * 查询需要推送的用户并且推送完修改为下一次提醒日期 + */ + public void pushRemind(){ + System.out.println(new Date()+"开始任务"); + try { + Class.forName("com.mysql.jdbc.Driver"); + connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/myfishdb?characterEncoding=UTF-8", "ifish", "ifish7pwd"); + stmt = connection.createStatement(); + prest = connection.prepareStatement("update tbl_tmp_push_remind set is_push=? where user_id=? and device_id=?"); + } catch (SQLException e) { + e.printStackTrace(); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + //结果集 + ResultSet result = null; + try { + //推送提醒数 + int rowCount = 0; + //按分页来获取数据 + int pageNo = 0; + //云信限制每次最多500条 + int pageSize = 500; + //查询总共需要推送的用户数 + String countSql = "select count(1) as countRow from tbl_tmp_push_remind where is_push='0'"; + result = stmt.executeQuery(countSql); + if(result.next()){ + rowCount=result.getInt("countRow"); + pageNo = (rowCount+pageSize-1)/pageSize; + } + System.out.println(pageNo); + for (int i = 0; i < pageNo; i++) { + result = stmt.executeQuery("select device_id,user_id,show_name,login_type from tbl_tmp_push_remind where is_push='0' limit 0,"+pageSize); + //推送的用户 + List androidUser = new ArrayList(); + List iosUser = new ArrayList(); + List ids = new ArrayList(); + //更新提醒过的用户 + while(result.next()){ + Integer deviceId= result.getInt("device_id"); + Integer userId = result.getInt("user_id"); + String loginType = result.getString("login_type"); + prest.setString(1, "1"); + prest.setInt(2, userId); + prest.setInt(3, deviceId); + prest.addBatch(); + //云信 + ids.add(userId.toString()); + //极光 + if(loginType.toLowerCase().equals(PhoneTypeEnum.android.getKey())){ + androidUser.add(userId.toString()); + } + else if(loginType.toLowerCase().equals(PhoneTypeEnum.ios.getKey())){ + iosUser.add(userId.toString()); + } + } + //发送云信消息 + if(ids.size()>0){ + neteaseIM.sendBatchMsg("ifish", JSONArray.fromObject(ids).toString(), "【换水提醒】您的水族箱需要换水啦~您可以在水箱设置中更改提醒设置"); + } + //极光推送 + Integer iosSize = iosUser.size(); + Integer androidSize = androidUser.size(); + if(iosSize>0){ + push(PhoneTypeEnum.ios,iosUser.toArray(new String[iosSize])); + } + if(androidSize>0){ + push(PhoneTypeEnum.android,androidUser.toArray(new String[androidSize])); + } + //批量提交 + prest.executeBatch(); + //云信一分钟访问不超过120次 + Thread.sleep(600); + } + } catch (Exception e) { + e.printStackTrace(); + } + finally{ + if(result!=null){ + try { + result.close(); + result = null; + } catch (SQLException e) { + e.printStackTrace(); + } + } + if(stmt!=null){ + try { + stmt.close(); + stmt = null; + } catch (SQLException e) { + e.printStackTrace(); + } + } + if(prest!=null){ + try { + prest.close(); + prest = null; + } catch (SQLException e) { + e.printStackTrace(); + } + } + if(connection!=null){ + try { + connection.close(); + connection = null; + } catch (SQLException e) { + e.printStackTrace(); + } + } + } + } + /** + * 推送提醒 + * @param type + * @param ids + */ + public void push(PhoneTypeEnum type,String[] ids){ + try { + Map map = new HashMap(); + map.put("timestamp", IfishUtil.format2(new Date())); + //推送android + /*if(type.equals(PhoneTypeEnum.android)){ + System.out.println(new Date()+"android推送"+ids.length+"个"); + jPushNotification.sendAndroidNotification(ids, "换水提醒", "您的水族箱需要换水啦~您可以在水箱设置中更改提醒设置", map); + }*/ + //推送IOS + if(type.equals(PhoneTypeEnum.ios)){ + System.out.println(new Date()+"ios推送"+ids.length+"个"); + jPushNotification2.sendIosNotification(ids, "换水提醒", "您的水族箱需要换水啦~您可以在水箱设置中更改提醒设置", map); + } + } catch (Exception e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/.svn/pristine/b3/b3eaa950e890123a437a2ea04a57255b1dbed628.svn-base b/.svn/pristine/b3/b3eaa950e890123a437a2ea04a57255b1dbed628.svn-base new file mode 100644 index 0000000..bffa040 --- /dev/null +++ b/.svn/pristine/b3/b3eaa950e890123a437a2ea04a57255b1dbed628.svn-base @@ -0,0 +1,157 @@ +package com.ifish.job; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.springframework.beans.factory.annotation.Autowired; + +import com.ifish.enums.PhoneTypeEnum; +import com.ifish.jpush.JPushNotification; +import com.ifish.util.IfishUtil; + +public class job{ + @Autowired + private JPushNotification jPushNotification; + @Autowired + private JPushNotification jPushNotification2; + + private Connection connection = null; + private Statement stmt = null; + private PreparedStatement prest = null; + + /** + * 查询需要推送的用户并且推送完修改为下一次提醒日期 + */ + public void pushRemind(){ + System.out.println(new Date()+"开始任务"); + try { + Class.forName("com.mysql.jdbc.Driver"); + connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/myfishdb?characterEncoding=UTF-8", "ifish", "ifish7pwd"); + stmt = connection.createStatement(); + prest = connection.prepareStatement("update tbl_tmp_push_remind set is_push=? where user_id=? and device_id=?"); + } catch (SQLException e) { + e.printStackTrace(); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + //结果集 + ResultSet result = null; + try { + //推送提醒数 + int rowCount = 0; + //按分页来获取数据 + int pageNo = 0; + int pageSize = 900; + //查询总共需要推送的用户数 + String countSql = "select count(1) as countRow from tbl_tmp_push_remind where is_push='0'"; + result = stmt.executeQuery(countSql); + if(result.next()){ + rowCount=result.getInt("countRow"); + pageNo = (rowCount+pageSize-1)/pageSize; + } + System.out.println(pageNo); + for (int i = 0; i < pageNo; i++) { + result = stmt.executeQuery("select device_id,user_id,show_name,login_type from tbl_tmp_push_remind where is_push='0' limit 0,"+pageSize); + //推送的用户 + List androidUser = new ArrayList(); + List iosUser = new ArrayList(); + //更新提醒过的用户 + while(result.next()){ + Integer deviceId= result.getInt("device_id"); + Integer userId = result.getInt("user_id"); + String loginType = result.getString("login_type"); + prest.setString(1, "1"); + prest.setInt(2, userId); + prest.setInt(3, deviceId); + prest.addBatch(); + if(loginType.toLowerCase().equals(PhoneTypeEnum.android.getKey())){ + androidUser.add(userId.toString()); + } + else if(loginType.toLowerCase().equals(PhoneTypeEnum.ios.getKey())){ + iosUser.add(userId.toString()); + } + } + //推送 + Integer iosSize = iosUser.size(); + Integer androidSize = androidUser.size(); + if(iosSize>0){ + push(PhoneTypeEnum.ios,iosUser.toArray(new String[iosSize])); + } + if(androidSize>0){ + System.out.println(androidUser.toString()); + push(PhoneTypeEnum.android,androidUser.toArray(new String[androidSize])); + } + //批量提交 + prest.executeBatch(); + } + } catch (SQLException e) { + e.printStackTrace(); + } + finally{ + if(result!=null){ + try { + result.close(); + result = null; + } catch (SQLException e) { + e.printStackTrace(); + } + } + if(stmt!=null){ + try { + stmt.close(); + stmt = null; + } catch (SQLException e) { + e.printStackTrace(); + } + } + if(prest!=null){ + try { + prest.close(); + prest = null; + } catch (SQLException e) { + e.printStackTrace(); + } + } + if(connection!=null){ + try { + connection.close(); + connection = null; + } catch (SQLException e) { + e.printStackTrace(); + } + } + } + } + /** + * 推送提醒 + * @param type + * @param ids + */ + public void push(PhoneTypeEnum type,String[] ids){ + try { + Map map = new HashMap(); + map.put("timestamp", IfishUtil.format2(new Date())); + //推送android + if(type.equals(PhoneTypeEnum.android)){ + System.out.println(new Date()+"android推送"+ids.length+"个"); + jPushNotification.sendAndroidNotification(ids, "换水提醒", "您的水族箱需要换水啦~您可以在水箱设置中更改提醒设置", map); + } + //推送IOS + else if(type.equals(PhoneTypeEnum.ios)){ + System.out.println(new Date()+"ios推送"+ids.length+"个"); + jPushNotification2.sendIosNotification(ids, "换水提醒", "您的水族箱需要换水啦~您可以在水箱设置中更改提醒设置", map); + } + } catch (Exception e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/.svn/pristine/b4/b435b36fb458ffe445bc484179aa76c524877a32.svn-base b/.svn/pristine/b4/b435b36fb458ffe445bc484179aa76c524877a32.svn-base new file mode 100644 index 0000000..f157947 --- /dev/null +++ b/.svn/pristine/b4/b435b36fb458ffe445bc484179aa76c524877a32.svn-base @@ -0,0 +1,61 @@ +package com.ifish.jpush.common.connection; + +import java.net.InetSocketAddress; +import java.net.Proxy; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.ifish.jpush.common.ServiceHelper; +import com.ifish.jpush.utils.Preconditions; + +public class HttpProxy { + private static final Logger LOG = LoggerFactory.getLogger(HttpProxy.class); + + private String host; + private int port; + private String username; + private String password; + + private boolean authenticationNeeded = false; + + public HttpProxy(String host, int port) { + this.host = host; + this.port = port; + } + + public HttpProxy(String host, int port, String username, String password) { + this(host, port); + + Preconditions.checkArgument(! (null == username), "username should not be null"); + Preconditions.checkArgument(! (null == password), "password should not be null"); + + this.username = username; + this.password = password; + authenticationNeeded = true; + + LOG.info("Http Proxy - host:" + host + ", port:" + port + + ", username:" + username + ", password:" + password); + } + + + public Proxy getNetProxy() { + return new Proxy(Proxy.Type.HTTP, new InetSocketAddress(host, port)); + } + + public boolean isAuthenticationNeeded() { + return this.authenticationNeeded; + } + + public String getProxyAuthorization() { + return ServiceHelper.getBasicAuthorization(username, password); + } + + public String getUsername() { + return this.username; + } + + public String getPassword() { + return this.password; + } +} diff --git a/.svn/pristine/b6/b6d6945c0f50e065acd39c9fb75448eac4af25f3.svn-base b/.svn/pristine/b6/b6d6945c0f50e065acd39c9fb75448eac4af25f3.svn-base new file mode 100644 index 0000000..a006513 --- /dev/null +++ b/.svn/pristine/b6/b6d6945c0f50e065acd39c9fb75448eac4af25f3.svn-base @@ -0,0 +1,39 @@ +package com.ifish.jpush.report; + +import java.util.ArrayList; +import java.util.List; + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; +import com.ifish.jpush.common.TimeUnit; +import com.ifish.jpush.common.resp.BaseResult; + +public class UsersResult extends BaseResult { + + @Expose public TimeUnit time_unit; + @Expose public String start; + @Expose public int duration; + @Expose public List items = new ArrayList(); + + + public static class User { + @Expose public String time; + @Expose public Android android; + @Expose public Ios ios; + } + + public static class Android { + @SerializedName("new") @Expose public long add; + @Expose public int online; + @Expose public int active; + } + + public static class Ios { + @SerializedName("new") @Expose public long add; + @Expose public int online; + @Expose public int active; + } + +} + + diff --git a/.svn/pristine/b7/b706e84fc8b85bae21c10f4025f3a84b9f4e23e8.svn-base b/.svn/pristine/b7/b706e84fc8b85bae21c10f4025f3a84b9f4e23e8.svn-base new file mode 100644 index 0000000..9b6a574 --- /dev/null +++ b/.svn/pristine/b7/b706e84fc8b85bae21c10f4025f3a84b9f4e23e8.svn-base @@ -0,0 +1,37 @@ + + + + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger{50} %msg%n + + + + + + ${LOG_HOME}/quartzPro/localhost.log + + ${LOG_HOME}/quartzPro/%d{yyyy-MM-dd}.log + 30 + + 100MB + + + + %d{yyyy-MM-dd HH:mm:ss} 【%-5level】 【%logger{50}】 %msg%n + UTF-8 + + + WARN + + + + + + + + + + + \ No newline at end of file diff --git a/.svn/pristine/b7/b7ceaa99fbad034b531d9587a425a9e0a3f00bbd.svn-base b/.svn/pristine/b7/b7ceaa99fbad034b531d9587a425a9e0a3f00bbd.svn-base new file mode 100644 index 0000000..e5d16a0 --- /dev/null +++ b/.svn/pristine/b7/b7ceaa99fbad034b531d9587a425a9e0a3f00bbd.svn-base @@ -0,0 +1,29 @@ +package com.ifish.enums; + +public enum PhoneTypeEnum { + ios("ios","ios"), + android("android","安卓"); + + private PhoneTypeEnum(String key,String value){ + this.key = key; + this.value = value; + } + + private String key; + private String value; + + + public String getKey() { + return key; + } + public void setKey(String key) { + this.key = key; + } + public String getValue() { + return value; + } + public void setValue(String value) { + this.value = value; + } + +} diff --git a/.svn/pristine/bb/bbccd5d3ec93b58b964171e92e1c29b173b057e3.svn-base b/.svn/pristine/bb/bbccd5d3ec93b58b964171e92e1c29b173b057e3.svn-base new file mode 100644 index 0000000..8fc0b0e --- /dev/null +++ b/.svn/pristine/bb/bbccd5d3ec93b58b964171e92e1c29b173b057e3.svn-base @@ -0,0 +1,108 @@ +package com.ifish.jpush.push.model; + +import java.util.HashSet; +import java.util.Set; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonPrimitive; +import com.ifish.jpush.common.DeviceType; +import com.ifish.jpush.utils.Preconditions; + +public class Platform implements PushModel { + private static final String ALL = "all"; + + private final boolean all; + private final Set deviceTypes; + + private Platform(boolean all, Set deviceTypes) { + this.all = all; + this.deviceTypes = deviceTypes; + } + + public static Builder newBuilder() { + return new Builder(); + } + + public static Platform all() { + return newBuilder().setAll(true).build(); + } + + public static Platform android() { + return newBuilder().addDeviceType(DeviceType.Android).build(); + } + + public static Platform ios() { + return newBuilder().addDeviceType(DeviceType.IOS).build(); + } + + public static Platform winphone() { + return newBuilder().addDeviceType(DeviceType.WinPhone).build(); + } + + public static Platform android_ios() { + return newBuilder() + .addDeviceType(DeviceType.Android) + .addDeviceType(DeviceType.IOS) + .build(); + } + + public static Platform android_winphone() { + return newBuilder() + .addDeviceType(DeviceType.Android) + .addDeviceType(DeviceType.WinPhone) + .build(); + } + + public static Platform ios_winphone() { + return newBuilder() + .addDeviceType(DeviceType.IOS) + .addDeviceType(DeviceType.WinPhone) + .build(); + } + + public boolean isAll() { + return all; + } + + @Override + public JsonElement toJSON() { + if (all) { + return new JsonPrimitive(ALL); + } + + JsonArray json = new JsonArray(); + for (DeviceType deviceType : deviceTypes) { + json.add(new JsonPrimitive(deviceType.value())); + } + return json; + } + + + public static class Builder { + private boolean all; + private Set deviceTypes; + + public Builder setAll(boolean all) { + this.all = all; + return this; + } + + public Builder addDeviceType(DeviceType deviceType) { + if (null == deviceTypes) { + deviceTypes = new HashSet(); + } + deviceTypes.add(deviceType); + return this; + } + + public Platform build() { + Preconditions.checkArgument(! (all && null != deviceTypes), "Since all is enabled, any platform should not be set."); + Preconditions.checkArgument(! (!all && null == deviceTypes), "No any deviceType is set."); + return new Platform(all, deviceTypes); + } + } + +} + + diff --git a/.svn/pristine/bc/bcfce3275a30b04ad638d76ba584ddbd2e8e647d.svn-base b/.svn/pristine/bc/bcfce3275a30b04ad638d76ba584ddbd2e8e647d.svn-base new file mode 100644 index 0000000..63276a1 --- /dev/null +++ b/.svn/pristine/bc/bcfce3275a30b04ad638d76ba584ddbd2e8e647d.svn-base @@ -0,0 +1,14 @@ +package com.ifish.jpush.device; + +import java.util.List; + +import com.google.gson.annotations.Expose; +import com.ifish.jpush.common.resp.BaseResult; + +public class TagAliasResult extends BaseResult { + + @Expose public List tags; + @Expose public String alias; + +} + diff --git a/.svn/pristine/bd/bd491e32befc373ab3d8bfbb2b314443d3a9f3d6.svn-base b/.svn/pristine/bd/bd491e32befc373ab3d8bfbb2b314443d3a9f3d6.svn-base new file mode 100644 index 0000000..3288fc4 --- /dev/null +++ b/.svn/pristine/bd/bd491e32befc373ab3d8bfbb2b314443d3a9f3d6.svn-base @@ -0,0 +1,107 @@ +package com.ifish.tianqi; + + +import javax.crypto.Mac; +import java.net.URLEncoder; +import java.security.InvalidKeyException; +import javax.crypto.spec.SecretKeySpec; + +public class javaDemo { + + private static final char last2byte = (char) Integer.parseInt("00000011", 2); + private static final char last4byte = (char) Integer.parseInt("00001111", 2); + private static final char last6byte = (char) Integer.parseInt("00111111", 2); + private static final char lead6byte = (char) Integer.parseInt("11111100", 2); + private static final char lead4byte = (char) Integer.parseInt("11110000", 2); + private static final char lead2byte = (char) Integer.parseInt("11000000", 2); + private static final char[] encodeTable = new char[] { 'A', 'B', 'C', 'D', + 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', + 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', + 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', + '4', '5', '6', '7', '8', '9', '+', '/' + }; + + public static String standardURLEncoder(String data, String key) { + byte[] byteHMAC = null; + String urlEncoder = ""; + try { + Mac mac = Mac.getInstance("HmacSHA1"); + SecretKeySpec spec = new SecretKeySpec(key.getBytes(), "HmacSHA1"); + mac.init(spec); + byteHMAC = mac.doFinal(data.getBytes()); + if (byteHMAC != null) { + String oauth = encode(byteHMAC); + if (oauth != null) { + urlEncoder = URLEncoder.encode(oauth, "utf8"); + } + } + } catch (InvalidKeyException e1) { + e1.printStackTrace(); + } catch (Exception e2) { + e2.printStackTrace(); + } + return urlEncoder; + } + + public static String encode(byte[] from) { + StringBuffer to = new StringBuffer((int) (from.length * 1.34) + 3); + int num = 0; + char currentByte = 0; + for (int i = 0; i < from.length; i++) { + num = num % 8; + while (num < 8) { + switch (num) { + case 0: + currentByte = (char) (from[i] & lead6byte); + currentByte = (char) (currentByte >>> 2); + break; + case 2: + currentByte = (char) (from[i] & last6byte); + break; + case 4: + currentByte = (char) (from[i] & last4byte); + currentByte = (char) (currentByte << 2); + if ((i + 1) < from.length) { + currentByte |= (from[i + 1] & lead2byte) >>> 6; + } + break; + case 6: + currentByte = (char) (from[i] & last2byte); + currentByte = (char) (currentByte << 4); + if ((i + 1) < from.length) { + currentByte |= (from[i + 1] & lead4byte) >>> 4; + } + break; + } + to.append(encodeTable[currentByte]); + num += 6; + } + } + if (to.length() % 4 != 0) { + for (int i = 4 - to.length() % 4; i > 0; i--) { + to.append("="); + } + } + return to.toString(); + } + + + public static void main(String[] args) { + try { + + //需要加密的数据 + String data = "http://open.weather.com.cn/data/?areaid=101020100&type=forecast_v&date=201603011100&appid=ee35072ca2850278"; + //密钥 + String key = "c4a99d_SmartWeatherAPI_a164e18"; + + String str = standardURLEncoder(data, key); + + System.out.println(str); + // http://open.weather.com.cn/data/?areaid=101020100&type=forecast_v&date=201603011100&appid=ee3507&key=WCD90OiAMNfP3g5qhdhXiUnyBnA%3D + + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/.svn/pristine/bf/bf24c84f94978ecd56df2d031e928a497b952ba3.svn-base b/.svn/pristine/bf/bf24c84f94978ecd56df2d031e928a497b952ba3.svn-base new file mode 100644 index 0000000..0066f02 --- /dev/null +++ b/.svn/pristine/bf/bf24c84f94978ecd56df2d031e928a497b952ba3.svn-base @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/.svn/pristine/c1/c1adf8303c9b905a6e1d405929c58eeb4d6ad040.svn-base b/.svn/pristine/c1/c1adf8303c9b905a6e1d405929c58eeb4d6ad040.svn-base new file mode 100644 index 0000000..596b3f2 --- /dev/null +++ b/.svn/pristine/c1/c1adf8303c9b905a6e1d405929c58eeb4d6ad040.svn-base @@ -0,0 +1,128 @@ +package com.ifish.jpush.push.model; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import com.ifish.jpush.common.ServiceHelper; +import com.ifish.jpush.utils.Preconditions; + +public class Options implements PushModel { + private static final String SENDNO = "sendno"; + private static final String OVERRIDE_MSG_ID = "override_msg_id"; + private static final String TIME_TO_LIVE = "time_to_live"; + private static final String APNS_PRODUCTION = "apns_production"; + private static final String BIG_PUSH_DURATION = "big_push_duration"; + + private static final long NONE_TIME_TO_LIVE = -1; + + private final int sendno; + private final long overrideMsgId; + private long timeToLive; + private boolean apnsProduction; + private int bigPushDuration; // minutes + + private Options(int sendno, long overrideMsgId, long timeToLive, boolean apnsProduction, + int bigPushDuration) { + this.sendno = sendno; + this.overrideMsgId = overrideMsgId; + this.timeToLive = timeToLive; + this.apnsProduction = apnsProduction; + this.bigPushDuration = bigPushDuration; + } + + public static Builder newBuilder() { + return new Builder(); + } + + public static Options sendno() { + return newBuilder().setSendno(ServiceHelper.generateSendno()).build(); + } + + public static Options sendno(int sendno) { + return newBuilder().setSendno(sendno).build(); + } + + public void setApnsProduction(boolean apnsProduction) { + this.apnsProduction = apnsProduction; + } + + public void setTimeToLive(long timeToLive) { + this.timeToLive = timeToLive; + } + + public void setBigPushDuration(int bigPushDuration) { + this.bigPushDuration = bigPushDuration; + } + + public int getSendno() { + return this.sendno; + } + + @Override + public JsonElement toJSON() { + JsonObject json = new JsonObject(); + if (sendno > 0) { + json.add(SENDNO, new JsonPrimitive(sendno)); + } + if (overrideMsgId > 0) { + json.add(OVERRIDE_MSG_ID, new JsonPrimitive(overrideMsgId)); + } + if (timeToLive >= 0) { + json.add(TIME_TO_LIVE, new JsonPrimitive(timeToLive)); + } + + json.add(APNS_PRODUCTION, new JsonPrimitive(apnsProduction)); + + if (bigPushDuration > 0) { + json.add(BIG_PUSH_DURATION, new JsonPrimitive(bigPushDuration)); + } + + return json; + } + + public static class Builder { + private int sendno = 0; + private long overrideMsgId = 0; + private long timeToLive = NONE_TIME_TO_LIVE; + private boolean apnsProduction = false; + private int bigPushDuration = 0; + + public Builder setSendno(int sendno) { + this.sendno = sendno; + return this; + } + + public Builder setOverrideMsgId(long overrideMsgId) { + this.overrideMsgId = overrideMsgId; + return this; + } + + public Builder setTimeToLive(long timeToLive) { + this.timeToLive = timeToLive; + return this; + } + + public Builder setApnsProduction(boolean apnsProduction) { + this.apnsProduction = apnsProduction; + return this; + } + + public Builder setBigPushDuration(int bigPushDuration) { + this.bigPushDuration = bigPushDuration; + return this; + } + + public Options build() { + Preconditions.checkArgument(sendno >= 0, "sendno should be greater than 0."); + Preconditions.checkArgument(overrideMsgId >= 0, "override_msg_id should be greater than 0."); + Preconditions.checkArgument(timeToLive >= NONE_TIME_TO_LIVE, "time_to_live should be greater than 0."); + Preconditions.checkArgument(bigPushDuration >= 0, "bigPushDuration should be greater than 0."); + if (sendno <= 0) { + sendno = ServiceHelper.generateSendno(); + } + + return new Options(sendno, overrideMsgId, timeToLive, apnsProduction, bigPushDuration); + } + } + +} diff --git a/.svn/pristine/c3/c3c66f0a4b971c3070f3f22a856c402bafb27cf0.svn-base b/.svn/pristine/c3/c3c66f0a4b971c3070f3f22a856c402bafb27cf0.svn-base new file mode 100644 index 0000000..4a43aef --- /dev/null +++ b/.svn/pristine/c3/c3c66f0a4b971c3070f3f22a856c402bafb27cf0.svn-base @@ -0,0 +1,17 @@ + + + Archetype Created Web Application + + index.jsp + + + contextConfigLocation + + classpath:quartz.xml + + + + org.springframework.web.context.ContextLoaderListener + + + \ No newline at end of file diff --git a/.svn/pristine/c4/c414204bcc55f784435fc0bbec4fdf0610b9cf10.svn-base b/.svn/pristine/c4/c414204bcc55f784435fc0bbec4fdf0610b9cf10.svn-base new file mode 100644 index 0000000..97577c0 --- /dev/null +++ b/.svn/pristine/c4/c414204bcc55f784435fc0bbec4fdf0610b9cf10.svn-base @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/.svn/pristine/ca/ca016d1d4f48d7aa2b6ea75639d53b124ad189a8.svn-base b/.svn/pristine/ca/ca016d1d4f48d7aa2b6ea75639d53b124ad189a8.svn-base new file mode 100644 index 0000000..5a7c6fb Binary files /dev/null and b/.svn/pristine/ca/ca016d1d4f48d7aa2b6ea75639d53b124ad189a8.svn-base differ diff --git a/.svn/pristine/d4/d484a833555f187f2c607a59d136f423ef3a0af4.svn-base b/.svn/pristine/d4/d484a833555f187f2c607a59d136f423ef3a0af4.svn-base new file mode 100644 index 0000000..04cad8c --- /dev/null +++ b/.svn/pristine/d4/d484a833555f187f2c607a59d136f423ef3a0af4.svn-base @@ -0,0 +1,2 @@ +disabled=06target +eclipse.preferences.version=1 diff --git a/.svn/pristine/d8/d890560ae3d9aa93d9140755d4e2dda5d67f8170.svn-base b/.svn/pristine/d8/d890560ae3d9aa93d9140755d4e2dda5d67f8170.svn-base new file mode 100644 index 0000000..4df6d69 --- /dev/null +++ b/.svn/pristine/d8/d890560ae3d9aa93d9140755d4e2dda5d67f8170.svn-base @@ -0,0 +1,10 @@ +package com.ifish.jpush.common; + +public enum TimeUnit { + + HOUR, + DAY, + MONTH, + WEEK + +} diff --git a/.svn/pristine/da/dac62c700e5adb0fc6496a747ed08369301a8bfc.svn-base b/.svn/pristine/da/dac62c700e5adb0fc6496a747ed08369301a8bfc.svn-base new file mode 100644 index 0000000..66dd7eb --- /dev/null +++ b/.svn/pristine/da/dac62c700e5adb0fc6496a747ed08369301a8bfc.svn-base @@ -0,0 +1,31 @@ +package com.ifish.util; + +import java.text.SimpleDateFormat; +import java.util.Date; + +public class IfishUtil { + + private static final String formatDate1 ="yyyy-MM-dd"; + private static final String formatDate2 ="yyyy-MM-dd HH:mm:ss"; + + /** + * 格式化日期yyyy-MM-dd HH:mm:ss + * @param date + * @return + */ + public static String format2(Date date){ + SimpleDateFormat format = new SimpleDateFormat(formatDate2); + return format.format(date); + } + + /** + * 格式化日期yyyy-MM-dd + * @param date + * @return + */ + public static String format1(Date date){ + SimpleDateFormat format = new SimpleDateFormat(formatDate1); + return format.format(date); + } + +} diff --git a/.svn/pristine/dc/dc9568b9c8f006a4af2c6400b3cbb76b657d1cce.svn-base b/.svn/pristine/dc/dc9568b9c8f006a4af2c6400b3cbb76b657d1cce.svn-base new file mode 100644 index 0000000..00f2066 --- /dev/null +++ b/.svn/pristine/dc/dc9568b9c8f006a4af2c6400b3cbb76b657d1cce.svn-base @@ -0,0 +1,148 @@ +package com.ifish.jpush.push.model.audience; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import com.ifish.jpush.push.model.PushModel; +import com.ifish.jpush.utils.Preconditions; + +public class Audience implements PushModel { + private static final String ALL = "all"; + + private final boolean all; + private final Set targets; + + private Audience(boolean all, Set targets) { + this.all = all; + this.targets = targets; + } + + public static Builder newBuilder() { + return new Builder(); + } + + public static Audience all() { + return newBuilder().setAll(true).build(); + } + + public static Audience tag(String... tagValue) { + AudienceTarget target = AudienceTarget.newBuilder() + .setAudienceType(AudienceType.TAG) + .addAudienceTargetValues(tagValue).build(); + return newBuilder().addAudienceTarget(target).build(); + } + + public static Audience tag(Collection tagValues) { + AudienceTarget target = AudienceTarget.newBuilder() + .setAudienceType(AudienceType.TAG) + .addAudienceTargetValues(tagValues).build(); + return newBuilder().addAudienceTarget(target).build(); + } + + public static Audience tag_and(String... tagValue) { + AudienceTarget target = AudienceTarget.newBuilder() + .setAudienceType(AudienceType.TAG_AND) + .addAudienceTargetValues(tagValue).build(); + return newBuilder().addAudienceTarget(target).build(); + } + + public static Audience tag_and(Collection tagValues) { + AudienceTarget target = AudienceTarget.newBuilder() + .setAudienceType(AudienceType.TAG_AND) + .addAudienceTargetValues(tagValues).build(); + return newBuilder().addAudienceTarget(target).build(); + } + + public static Audience alias(String... alias) { + AudienceTarget target = AudienceTarget.newBuilder() + .setAudienceType(AudienceType.ALIAS) + .addAudienceTargetValues(alias).build(); + return newBuilder().addAudienceTarget(target).build(); + } + + public static Audience alias(Collection aliases) { + AudienceTarget target = AudienceTarget.newBuilder() + .setAudienceType(AudienceType.ALIAS) + .addAudienceTargetValues(aliases).build(); + return newBuilder().addAudienceTarget(target).build(); + } + + public static Audience segment(String... segment) { + AudienceTarget target = AudienceTarget.newBuilder() + .setAudienceType(AudienceType.SEGMENT) + .addAudienceTargetValues(segment).build(); + return newBuilder().addAudienceTarget(target).build(); + } + + public static Audience segment(Collection segments) { + AudienceTarget target = AudienceTarget.newBuilder() + .setAudienceType(AudienceType.SEGMENT) + .addAudienceTargetValues(segments).build(); + return newBuilder().addAudienceTarget(target).build(); + } + + public static Audience registrationId(String... registrationId) { + AudienceTarget target = AudienceTarget.newBuilder() + .setAudienceType(AudienceType.REGISTRATION_ID) + .addAudienceTargetValues(registrationId).build(); + return newBuilder().addAudienceTarget(target).build(); + } + + public static Audience registrationId(Collection registrationIds) { + AudienceTarget target = AudienceTarget.newBuilder() + .setAudienceType(AudienceType.REGISTRATION_ID) + .addAudienceTargetValues(registrationIds).build(); + return newBuilder().addAudienceTarget(target).build(); + } + + + public boolean isAll() { + return this.all; + } + + public JsonElement toJSON() { + if (all) { + return new JsonPrimitive(ALL); + } + + // if not all, there will be target be set. + JsonObject json = new JsonObject(); + if (null != targets) { + for (AudienceTarget target : targets) { + json.add(target.getAudienceTypeValue(), target.toJSON()); + } + } + return json; + } + + public static class Builder { + private boolean all = false; + private Set audienceBuilder = null; + + public Builder setAll(boolean all) { + this.all = all; + return this; + } + + public Builder addAudienceTarget(AudienceTarget target) { + if (null == audienceBuilder) { + audienceBuilder = new HashSet(); + } + audienceBuilder.add(target); + return this; + } + + public Audience build() { + Preconditions.checkArgument(! (all && null != audienceBuilder), "If audience is all, no any other audience may be set."); + Preconditions.checkArgument(! (all == false && null == audienceBuilder), "No any audience target is set."); + return new Audience(all, audienceBuilder); + } + } + +} + + diff --git a/.svn/pristine/df/dfc05dd4812eaf19bc73b84b94a11ee724fd0956.svn-base b/.svn/pristine/df/dfc05dd4812eaf19bc73b84b94a11ee724fd0956.svn-base new file mode 100644 index 0000000..e2b3956 --- /dev/null +++ b/.svn/pristine/df/dfc05dd4812eaf19bc73b84b94a11ee724fd0956.svn-base @@ -0,0 +1,9 @@ +package com.ifish.jpush.common.resp; + +import com.google.gson.annotations.Expose; + +public class BooleanResult extends DefaultResult { + + @Expose public boolean result; + +} diff --git a/.svn/pristine/e2/e2000b073a99f5394df7fff808102576f780240b.svn-base b/.svn/pristine/e2/e2000b073a99f5394df7fff808102576f780240b.svn-base new file mode 100644 index 0000000..f1d1602 --- /dev/null +++ b/.svn/pristine/e2/e2000b073a99f5394df7fff808102576f780240b.svn-base @@ -0,0 +1,68 @@ +package com.ifish.jpush.examples; + +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.ifish.jpush.JPushClient; +import com.ifish.jpush.common.resp.APIConnectionException; +import com.ifish.jpush.common.resp.APIRequestException; +import com.ifish.jpush.device.OnlineStatus; +import com.ifish.jpush.device.TagAliasResult; + +public class DevcieExample { + protected static final Logger LOG = LoggerFactory.getLogger(DevcieExample.class); + + private static final String appKey = "dd1066407b044738b6479275"; + private static final String masterSecret = "6b135be0037a5c1e693c3dfa"; + private static final String TAG1 = "tag1"; + private static final String ALIAS1 = "alias1"; + private static final String ALIAS2 = "alias2"; + private static final String REGISTRATION_ID1 = "0900e8d85ef"; + private static final String REGISTRATION_ID2 = "0a04ad7d8b4"; + + private static JPushClient jpushClient = new JPushClient(masterSecret, appKey); + + public static void main(String[] args) { +// testGetDeviceTagAlias(); + testGetUserOnlineStatus(); + } + + public static void testGetDeviceTagAlias() { + try { + TagAliasResult result = jpushClient.getDeviceTagAlias(REGISTRATION_ID1); + + LOG.info(result.alias); + LOG.info(result.tags.toString()); + + } catch (APIConnectionException e) { + LOG.error("Connection error. Should retry later. ", e); + + } catch (APIRequestException e) { + LOG.error("Error response from JPush server. Should review and fix it. ", e); + LOG.info("HTTP Status: " + e.getStatus()); + LOG.info("Error Code: " + e.getErrorCode()); + LOG.info("Error Message: " + e.getErrorMessage()); + } + } + + public static void testGetUserOnlineStatus() { + try { + Map result = jpushClient.getUserOnlineStatus(REGISTRATION_ID1, REGISTRATION_ID2); + + LOG.info(result.get(REGISTRATION_ID1).toString()); + LOG.info(result.get(REGISTRATION_ID2).toString()); + } catch (APIConnectionException e) { + LOG.error("Connection error. Should retry later. ", e); + } catch (APIRequestException e) { + LOG.error("Error response from JPush server. Should review and fix it. ", e); + LOG.info("HTTP Status: " + e.getStatus()); + LOG.info("Error Code: " + e.getErrorCode()); + LOG.info("Error Message: " + e.getErrorMessage()); + } + } + +} + + diff --git a/.svn/pristine/e3/e3057d3ba6db57f138c76d4bf1f23a9906bbfa8f.svn-base b/.svn/pristine/e3/e3057d3ba6db57f138c76d4bf1f23a9906bbfa8f.svn-base new file mode 100644 index 0000000..e7340bf --- /dev/null +++ b/.svn/pristine/e3/e3057d3ba6db57f138c76d4bf1f23a9906bbfa8f.svn-base @@ -0,0 +1,31 @@ +package com.ifish.jpush.schedule; + + +import java.util.List; + +import com.google.gson.annotations.Expose; +import com.ifish.jpush.common.resp.BaseResult; + +public class ScheduleListResult extends BaseResult{ + + @Expose int total_count; + @Expose int total_pages; + @Expose int page; + @Expose List schedules; + + public int getTotal_count() { + return total_count; + } + + public int getTotal_pages() { + return total_pages; + } + + public int getPage() { + return page; + } + + public List getSchedules() { + return schedules; + } +} diff --git a/.svn/pristine/e6/e6b4793cda7267c5f22d39a849da2a9d901d2eb0.svn-base b/.svn/pristine/e6/e6b4793cda7267c5f22d39a849da2a9d901d2eb0.svn-base new file mode 100644 index 0000000..f5d9316 --- /dev/null +++ b/.svn/pristine/e6/e6b4793cda7267c5f22d39a849da2a9d901d2eb0.svn-base @@ -0,0 +1,12 @@ +package com.ifish.jpush.common.resp; + +public interface IRateLimiting { + + public int getRateLimitQuota(); + + public int getRateLimitRemaining(); + + public int getRateLimitReset(); + +} + diff --git a/.svn/pristine/e9/e9856d0dd103d59a7ca563d919d983470d81e004.svn-base b/.svn/pristine/e9/e9856d0dd103d59a7ca563d919d983470d81e004.svn-base new file mode 100644 index 0000000..254272e --- /dev/null +++ b/.svn/pristine/e9/e9856d0dd103d59a7ca563d919d983470d81e004.svn-base @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Class-Path: + diff --git a/.svn/pristine/eb/eb2d8b5f7c7c38e5af1c91bd8cfde995df5ea1c4.svn-base b/.svn/pristine/eb/eb2d8b5f7c7c38e5af1c91bd8cfde995df5ea1c4.svn-base new file mode 100644 index 0000000..bf774a3 --- /dev/null +++ b/.svn/pristine/eb/eb2d8b5f7c7c38e5af1c91bd8cfde995df5ea1c4.svn-base @@ -0,0 +1,68 @@ +package com.ifish.jpush.common.connection; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.ifish.jpush.common.resp.APIConnectionException; +import com.ifish.jpush.common.resp.APIRequestException; +import com.ifish.jpush.common.resp.ResponseWrapper; + +public interface IHttpClient { + + public static final String CHARSET = "UTF-8"; + public static final String CONTENT_TYPE_JSON = "application/json"; + public static final String CONTENT_TYPE_FORM = "application/x-www-form-urlencoded"; + + public static final String RATE_LIMIT_QUOTA = "X-Rate-Limit-Limit"; + public static final String RATE_LIMIT_Remaining = "X-Rate-Limit-Remaining"; + public static final String RATE_LIMIT_Reset = "X-Rate-Limit-Reset"; + public static final String JPUSH_USER_AGENT = "JPush-API-Java-Client"; + + public static final int RESPONSE_OK = 200; + + public enum RequestMethod { + GET, + POST, + PUT, + DELETE + } + + public static final String IO_ERROR_MESSAGE = "Connection IO error. \n" + + "Can not connect to JPush Server. " + + "Please ensure your internet connection is ok. \n" + + "If the problem persists, please let us know at support@jpush.cn."; + + public static final String CONNECT_TIMED_OUT_MESSAGE = "connect timed out. \n" + + "Connect to JPush Server timed out, and already retried some times. \n" + + "Please ensure your internet connection is ok. \n" + + "If the problem persists, please let us know at support@jpush.cn."; + + public static final String READ_TIMED_OUT_MESSAGE = "Read timed out. \n" + + "Read response from JPush Server timed out. \n" + + "If this is a Push action, you may not want to retry. \n" + + "It may be due to slowly response from JPush server, or unstable connection. \n" + + "If the problem persists, please let us know at support@jpush.cn."; + + public static Gson _gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create(); + + + //设置连接超时时间 + public static final int DEFAULT_CONNECTION_TIMEOUT = (5 * 1000); // milliseconds + + //设置读取超时时间 + public static final int DEFAULT_READ_TIMEOUT = (30 * 1000); // milliseconds + + public static final int DEFAULT_MAX_RETRY_TIMES = 3; + + public ResponseWrapper sendGet(String url) + throws APIConnectionException, APIRequestException; + + public ResponseWrapper sendDelete(String url) + throws APIConnectionException, APIRequestException; + + public ResponseWrapper sendPost(String url, String content) + throws APIConnectionException, APIRequestException; + + + public ResponseWrapper sendPut(String url, String content) + throws APIConnectionException, APIRequestException; +} diff --git a/.svn/pristine/eb/ebd11658aae083ea7c3c68857896b9e838bad001.svn-base b/.svn/pristine/eb/ebd11658aae083ea7c3c68857896b9e838bad001.svn-base new file mode 100644 index 0000000..f37558d --- /dev/null +++ b/.svn/pristine/eb/ebd11658aae083ea7c3c68857896b9e838bad001.svn-base @@ -0,0 +1,11 @@ +package com.ifish.jpush.common; + +public enum Week { + MON, + TUE, + WED, + THU, + FRI, + SAT, + SUN +} diff --git a/.svn/pristine/f5/f55db755b6f0fc57bbf923919fbe41367430df63.svn-base b/.svn/pristine/f5/f55db755b6f0fc57bbf923919fbe41367430df63.svn-base new file mode 100644 index 0000000..99f26c0 --- /dev/null +++ b/.svn/pristine/f5/f55db755b6f0fc57bbf923919fbe41367430df63.svn-base @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/.svn/pristine/f6/f6664b7f5095c93ef8f31f9c4f185b70bb777223.svn-base b/.svn/pristine/f6/f6664b7f5095c93ef8f31f9c4f185b70bb777223.svn-base new file mode 100644 index 0000000..f20d58c --- /dev/null +++ b/.svn/pristine/f6/f6664b7f5095c93ef8f31f9c4f185b70bb777223.svn-base @@ -0,0 +1,32 @@ +c3p0.driverClassName=com.mysql.jdbc.Driver +c3p0.url=jdbc\:mysql\://localhost\:3306/myfishdb?characterEncoding\=UTF-8 +c3p0.username=ifish +c3p0.password=ifish7pwd +#c3p0.username=root +#c3p0.password=123456 + +c3p0.autoCommitOnClose=true +c3p0.initialPoolSize=50 +c3p0.minPoolSize=50 +c3p0.maxPoolSize=100 +c3p0.acquireIncrement=3 + +c3p0.checkoutTimeout=5000 +c3p0.maxIdleTime=7200 +c3p0.idleConnectionTestPeriod=18000 +#c3p0.maxIdleTimeExcessConnections=1800 + +#c3p0.automaticTestTable=C3P0TestTable +#c3p0.testConnectionOnCheckout=false +#c3p0.testConnectionOnCheckin=false + +#org.hibernate.dialect.MySQLInnoDBDialect +hibernate.dialect=org.hibernate.dialect.MySQLDialect +hibernate.show_sql=false +hibernate.format_sql=true +hibernate.hbm2ddl.auto=false +hibernate.jdbc.batch_size=50 +hibernate.query.substitutions=true 1,false 0 +hibernate.cache.use_second_level_cache=false +hibernate.cache.use_query_cache=false +hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory \ No newline at end of file diff --git a/.svn/pristine/f7/f7fedbddb795244d60e0d1e4b6582118f3717188.svn-base b/.svn/pristine/f7/f7fedbddb795244d60e0d1e4b6582118f3717188.svn-base new file mode 100644 index 0000000..57416c9 --- /dev/null +++ b/.svn/pristine/f7/f7fedbddb795244d60e0d1e4b6582118f3717188.svn-base @@ -0,0 +1,89 @@ + + + + + + + + + + + + + true + + + + + + + + + + + + + 0 15 8 * * ? + + + + + + + + + + + pushRemind + + + + + + + + + + + + + + + + + ${jpush.android.appKey} + + + + ${jpush.android.secret} + + + + ${jpush.android.productionMode} + + + + + + + ${jpush.ios.appKey} + + + + ${jpush.ios.secret} + + + + ${jpush.ios.productionMode} + + + \ No newline at end of file diff --git a/.svn/pristine/f9/f90e15d5d57f8ea3fe7a30c500f96082c068b590.svn-base b/.svn/pristine/f9/f90e15d5d57f8ea3fe7a30c500f96082c068b590.svn-base new file mode 100644 index 0000000..31b8b29 --- /dev/null +++ b/.svn/pristine/f9/f90e15d5d57f8ea3fe7a30c500f96082c068b590.svn-base @@ -0,0 +1,219 @@ +package com.ifish.jpush.push.model; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import com.ifish.jpush.push.model.audience.Audience; +import com.ifish.jpush.push.model.notification.AndroidNotification; +import com.ifish.jpush.push.model.notification.IosNotification; +import com.ifish.jpush.push.model.notification.Notification; +import com.ifish.jpush.push.model.notification.PlatformNotification; +import com.ifish.jpush.utils.Preconditions; + +/** + * The object you should build for sending a push. + * + * Basically start with newBuilder() method to build a PushPayload object. + * + * alertAll() is a shortcut for quickly build payload of alert to all platform and all audience; + * mesageAll() is a shortcut for quickly build payload of message to all platform and all audience. + * + */ +public class PushPayload implements PushModel { + private static final String PLATFORM = "platform"; + private static final String AUDIENCE = "audience"; + private static final String NOTIFICATION = "notification"; + private static final String MESSAGE = "message"; + private static final String OPTIONS = "options"; + + private static final int MAX_GLOBAL_ENTITY_LENGTH = 1200; // Definition acording to JPush Docs + private static final int MAX_IOS_PAYLOAD_LENGTH = 220; // Definition acording to JPush Docs + + private static Gson _gson = new Gson(); + + private final Platform platform; + private final Audience audience; + private final Notification notification; + private final Message message; + private Options options; + + + private PushPayload(Platform platform, Audience audience, + Notification notification, Message message, Options options) { + this.platform = platform; + this.audience = audience; + this.notification = notification; + this.message = message; + this.options = options; + } + + /** + * The entrance for building a PushPayload object. + */ + public static Builder newBuilder() { + return new Builder(); + } + + /** + * The shortcut of building a simple alert notification object to all platforms and all audiences + */ + public static PushPayload alertAll(String alert) { + return new Builder() + .setPlatform(Platform.all()) + .setAudience(Audience.all()) + .setNotification(Notification.alert(alert)).build(); + } + + /** + * The shortcut of building a simple message object to all platforms and all audiences + */ + public static PushPayload messageAll(String msgContent) { + return new Builder() + .setPlatform(Platform.all()) + .setAudience(Audience.all()) + .setMessage(Message.content(msgContent)).build(); + } + + public static PushPayload fromJSON(String payloadString) { + return _gson.fromJson(payloadString, PushPayload.class); + } + + public void resetOptionsApnsProduction(boolean apnsProduction) { + if (null == options) { + options = Options.newBuilder().setApnsProduction(apnsProduction).build(); + } else { + options.setApnsProduction(apnsProduction); + } + } + + public void resetOptionsTimeToLive(long timeToLive) { + if (null == options) { + options = Options.newBuilder().setTimeToLive(timeToLive).build(); + } else { + options.setTimeToLive(timeToLive); + } + } + + public int getSendno() { + if (null != options) { + return options.getSendno(); + } + return 0; + } + + @Override + public JsonElement toJSON() { + JsonObject json = new JsonObject(); + if (null != platform) { + json.add(PLATFORM, platform.toJSON()); + } + if (null != audience) { + json.add(AUDIENCE, audience.toJSON()); + } + if (null != notification) { + json.add(NOTIFICATION, notification.toJSON()); + } + if (null != message) { + json.add(MESSAGE, message.toJSON()); + } + if (null != options) { + json.add(OPTIONS, options.toJSON()); + } + + return json; + } + + public boolean isGlobalExceedLength() { + int messageLength = 0; + JsonObject payload = (JsonObject) this.toJSON(); + if (payload.has(MESSAGE)) { + JsonObject message = payload.getAsJsonObject(MESSAGE); + messageLength = message.toString().getBytes().length; + } + if (!payload.has(NOTIFICATION)) { + // only mesage + return messageLength > MAX_GLOBAL_ENTITY_LENGTH; + } else { + JsonObject notification = payload.getAsJsonObject(NOTIFICATION); + if (notification.has(AndroidNotification.NOTIFICATION_ANDROID)) { + JsonObject android = notification.getAsJsonObject(AndroidNotification.NOTIFICATION_ANDROID); + int androidLength = android.toString().getBytes().length; + return (androidLength + messageLength) > MAX_GLOBAL_ENTITY_LENGTH; + } + } + return false; + } + + public boolean isIosExceedLength() { + JsonObject payload = (JsonObject) this.toJSON(); + if (payload.has(NOTIFICATION)) { + JsonObject notification = payload.getAsJsonObject(NOTIFICATION); + if (notification.has(IosNotification.NOTIFICATION_IOS)) { + JsonObject ios = notification.getAsJsonObject(IosNotification.NOTIFICATION_IOS); + return ios.toString().getBytes().length > MAX_IOS_PAYLOAD_LENGTH; + } else { + if (notification.has(PlatformNotification.ALERT)) { + String alert = notification.get(PlatformNotification.ALERT).getAsString(); + JsonObject ios = new JsonObject(); + ios.add("alert", new JsonPrimitive(alert)); + return ios.toString().getBytes().length > MAX_IOS_PAYLOAD_LENGTH; + } else { + // No iOS Payload + } + } + } + return false; + } + + @Override + public String toString() { + return _gson.toJson(toJSON()); + } + + public static class Builder { + private Platform platform = null; + private Audience audience = null; + private Notification notification = null; + private Message message = null; + private Options options = null; + + public Builder setPlatform(Platform platform) { + this.platform = platform; + return this; + } + + public Builder setAudience(Audience audience) { + this.audience = audience; + return this; + } + + public Builder setNotification(Notification notification) { + this.notification = notification; + return this; + } + + public Builder setMessage(Message message) { + this.message = message; + return this; + } + + public Builder setOptions(Options options) { + this.options = options; + return this; + } + + public PushPayload build() { + Preconditions.checkArgument(! (null == audience || null == platform), "audience and platform both should be set."); + Preconditions.checkArgument(! (null == notification && null == message), "notification or message should be set at least one."); + + // if options is not set, a sendno will be generated for tracing easily + if (null == options) { + options = Options.sendno(); + } + + return new PushPayload(platform, audience, notification, message, options); + } + } +} + diff --git a/.svn/pristine/fa/faec2dce1b2e943c992a3a40f589ae0e1a06555e.svn-base b/.svn/pristine/fa/faec2dce1b2e943c992a3a40f589ae0e1a06555e.svn-base new file mode 100644 index 0000000..0c8a455 --- /dev/null +++ b/.svn/pristine/fa/faec2dce1b2e943c992a3a40f589ae0e1a06555e.svn-base @@ -0,0 +1,19 @@ +package com.ifish.jpush.common; + +public enum DeviceType { + + Android("android"), + IOS("ios"), + WinPhone("winphone"); + + private final String value; + + private DeviceType(final String value) { + this.value = value; + } + + public String value() { + return this.value; + } + +} diff --git a/.svn/pristine/fb/fb6df4bc51fcdb123382c6bc2079398c8d4e5b49.svn-base b/.svn/pristine/fb/fb6df4bc51fcdb123382c6bc2079398c8d4e5b49.svn-base new file mode 100644 index 0000000..b0e5062 --- /dev/null +++ b/.svn/pristine/fb/fb6df4bc51fcdb123382c6bc2079398c8d4e5b49.svn-base @@ -0,0 +1,28 @@ +package com.ifish.enums; + +public enum NeteaseEnum { + status200("200","操作成功"), + status414("414","参数错误"); + + private NeteaseEnum(String key,String value){ + this.key = key; + this.value = value; + } + + private String key; + private String value; + + + public String getKey() { + return key; + } + public void setKey(String key) { + this.key = key; + } + public String getValue() { + return value; + } + public void setValue(String value) { + this.value = value; + } +} diff --git a/.svn/pristine/fc/fc8385fe2a56ae21b12d5e6b0684ec2974cbcbcb.svn-base b/.svn/pristine/fc/fc8385fe2a56ae21b12d5e6b0684ec2974cbcbcb.svn-base new file mode 100644 index 0000000..8f72326 --- /dev/null +++ b/.svn/pristine/fc/fc8385fe2a56ae21b12d5e6b0684ec2974cbcbcb.svn-base @@ -0,0 +1,121 @@ +package com.ifish.jpush.push.model.audience; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonPrimitive; +import com.ifish.jpush.push.model.PushModel; +import com.ifish.jpush.utils.Preconditions; + +public class AudienceTarget implements PushModel { + private final AudienceType audienceType; + private final Set values; + + private AudienceTarget(AudienceType audienceType, Set values) { + this.audienceType = audienceType; + this.values = values; + } + + public static Builder newBuilder() { + return new Builder(); + } + + public static AudienceTarget tag(String... tag) { + return newBuilder().setAudienceType(AudienceType.TAG).addAudienceTargetValues(tag).build(); + } + + public static AudienceTarget tag(Collection tags) { + return newBuilder().setAudienceType(AudienceType.TAG).addAudienceTargetValues(tags).build(); + } + + public static AudienceTarget tag_and(String... tag) { + return newBuilder().setAudienceType(AudienceType.TAG_AND).addAudienceTargetValues(tag).build(); + } + + public static AudienceTarget tag_and(Collection tags) { + return newBuilder().setAudienceType(AudienceType.TAG_AND).addAudienceTargetValues(tags).build(); + } + + public static AudienceTarget alias(String... alias) { + return newBuilder().setAudienceType(AudienceType.ALIAS).addAudienceTargetValues(alias).build(); + } + + public static AudienceTarget alias(Collection aliases) { + return newBuilder().setAudienceType(AudienceType.ALIAS).addAudienceTargetValues(aliases).build(); + } + + public static AudienceTarget registrationId(String... registrationId) { + return newBuilder().setAudienceType(AudienceType.REGISTRATION_ID).addAudienceTargetValues(registrationId).build(); + } + + public static AudienceTarget registrationId(Collection registrationIds) { + return newBuilder().setAudienceType(AudienceType.REGISTRATION_ID).addAudienceTargetValues(registrationIds).build(); + } + + + public AudienceType getAudienceType() { + return this.audienceType; + } + + public String getAudienceTypeValue() { + return this.audienceType.value(); + } + + public JsonElement toJSON() { + JsonArray array = new JsonArray(); + if (null != values) { + for (String value : values) { + array.add(new JsonPrimitive(value)); + } + } + return array; + } + + + public static class Builder { + private AudienceType audienceType = null; + private Set valueBuilder = null; + + public Builder setAudienceType(AudienceType audienceType) { + this.audienceType = audienceType; + return this; + } + + public Builder addAudienceTargetValue(String value) { + if (null == valueBuilder) { + valueBuilder = new HashSet(); + } + valueBuilder.add(value); + return this; + } + + public Builder addAudienceTargetValues(Collection values) { + if (null == valueBuilder) { + valueBuilder = new HashSet(); + } + for (String value : values) { + valueBuilder.add(value); + } + return this; + } + + public Builder addAudienceTargetValues(String... values) { + if (null == valueBuilder) { + valueBuilder = new HashSet(); + } + for (String value : values) { + valueBuilder.add(value); + } + return this; + } + + public AudienceTarget build() { + Preconditions.checkArgument(null != audienceType, "AudienceType should be set."); + Preconditions.checkArgument(null != valueBuilder, "Target values should be set one at least."); + return new AudienceTarget(audienceType, valueBuilder); + } + } +} diff --git a/.svn/pristine/fd/fdc29977898af9c32cf100135a7a59c6cf931041.svn-base b/.svn/pristine/fd/fdc29977898af9c32cf100135a7a59c6cf931041.svn-base new file mode 100644 index 0000000..c28caa4 --- /dev/null +++ b/.svn/pristine/fd/fdc29977898af9c32cf100135a7a59c6cf931041.svn-base @@ -0,0 +1,87 @@ +package com.ifish.jpush.push.model.notification; + +import java.util.Map; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; + +public class WinphoneNotification extends PlatformNotification { + private static final String NOTIFICATION_WINPHONE = "winphone"; + + private static final String TITLE = "title"; + private static final String _OPEN_PAGE = "_open_page"; + + private final String title; + private final String openPage; + + private WinphoneNotification(Object alert, String title, String openPage, + Map extras, + Map numberExtras, + Map booleanExtras, + Map jsonExtras) { + super(alert, extras, numberExtras, booleanExtras, jsonExtras); + + this.title = title; + this.openPage = openPage; + } + + public static Builder newBuilder() { + return new Builder(); + } + + public static WinphoneNotification alert(String alert) { + return newBuilder().setAlert(alert).build(); + } + + + @Override + public String getPlatform() { + return NOTIFICATION_WINPHONE; + } + + @Override + public JsonElement toJSON() { + JsonObject json = super.toJSON().getAsJsonObject(); + + if (null != title) { + json.add(TITLE, new JsonPrimitive(title)); + } + if (null != openPage) { + json.add(_OPEN_PAGE, new JsonPrimitive(openPage)); + } + + return json; + } + + + public static class Builder extends PlatformNotification.Builder { + private String title; + private String openPage; + + protected Builder getThis() { + return this; + } + + public Builder setTitle(String title) { + this.title = title; + return this; + } + + public Builder setOpenPage(String openPage) { + this.openPage = openPage; + return this; + } + + public Builder setAlert(Object alert) { + this.alert = alert; + return this; + } + + + public WinphoneNotification build() { + return new WinphoneNotification(alert, title, openPage, + extrasBuilder, numberExtrasBuilder, booleanExtrasBuilder, jsonExtrasBuilder); + } + } +} diff --git a/.svn/wc.db b/.svn/wc.db new file mode 100644 index 0000000..9088ed2 Binary files /dev/null and b/.svn/wc.db differ diff --git a/nb-configuration.xml b/nb-configuration.xml new file mode 100644 index 0000000..4735c89 --- /dev/null +++ b/nb-configuration.xml @@ -0,0 +1,18 @@ + + + + + + Tomcat + + diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..38f1146 --- /dev/null +++ b/pom.xml @@ -0,0 +1,184 @@ + + 4.0.0 + quartzPro + quartzPro + war + 0.0.1-SNAPSHOT + quartzPro + http://mvnrepository.com + + + + + org.quartz-scheduler + quartz + 2.2.1 + + + + net.sf.json-lib + json-lib + 2.4 + jdk15 + + + + org.apache.httpcomponents + httpclient + 4.3.5 + + + + javax.servlet + javax.servlet-api + 3.0.1 + + + + org.springframework + spring-core + 4.1.6.RELEASE + + + + org.springframework + spring-context + 4.1.6.RELEASE + + + + org.springframework + spring-context-support + 4.1.6.RELEASE + + + + org.aspectj + aspectjweaver + 1.8.5 + + + + org.springframework + spring-aspects + 4.1.6.RELEASE + + + + org.springframework + spring-orm + 4.1.6.RELEASE + + + + org.springframework + spring-beans + 4.1.6.RELEASE + + + + org.springframework + spring-aop + 4.1.6.RELEASE + + + + org.springframework + spring-webmvc + 4.1.6.RELEASE + + + + c3p0 + c3p0 + 0.9.1.2 + + + + org.slf4j + slf4j-api + 1.7.12 + + + + ch.qos.logback + logback-core + 1.1.2 + + + + ch.qos.logback + logback-classic + 1.1.2 + + + + org.hibernate + hibernate-core + 4.3.11.Final + + + + org.jboss.logging + jboss-logging-annotations + 2.0.1.Final + + + + org.json + json + 20090211 + + + + com.google.code.gson + gson + 2.3 + + + + + quartzPro + + + org.apache.maven.plugins + maven-war-plugin + 2.4 + + + + src/main/webapp + + + + + + org.apache.felix + maven-bundle-plugin + 2.5.4 + true + + + + + src/main/java + + **/*.hbm.xml + + + + src/main/resources + + **/*.xml + **/*.properties + + + + + + + UTF-8 + + + diff --git a/src/main/java/com/ifish/enums/NeteaseEnum.java b/src/main/java/com/ifish/enums/NeteaseEnum.java new file mode 100644 index 0000000..b0e5062 --- /dev/null +++ b/src/main/java/com/ifish/enums/NeteaseEnum.java @@ -0,0 +1,28 @@ +package com.ifish.enums; + +public enum NeteaseEnum { + status200("200","操作成功"), + status414("414","参数错误"); + + private NeteaseEnum(String key,String value){ + this.key = key; + this.value = value; + } + + private String key; + private String value; + + + public String getKey() { + return key; + } + public void setKey(String key) { + this.key = key; + } + public String getValue() { + return value; + } + public void setValue(String value) { + this.value = value; + } +} diff --git a/src/main/java/com/ifish/enums/PhoneTypeEnum.java b/src/main/java/com/ifish/enums/PhoneTypeEnum.java new file mode 100644 index 0000000..e5d16a0 --- /dev/null +++ b/src/main/java/com/ifish/enums/PhoneTypeEnum.java @@ -0,0 +1,29 @@ +package com.ifish.enums; + +public enum PhoneTypeEnum { + ios("ios","ios"), + android("android","安卓"); + + private PhoneTypeEnum(String key,String value){ + this.key = key; + this.value = value; + } + + private String key; + private String value; + + + public String getKey() { + return key; + } + public void setKey(String key) { + this.key = key; + } + public String getValue() { + return value; + } + public void setValue(String value) { + this.value = value; + } + +} diff --git a/src/main/java/com/ifish/enums/PushTypeEnum.java b/src/main/java/com/ifish/enums/PushTypeEnum.java new file mode 100644 index 0000000..72eb823 --- /dev/null +++ b/src/main/java/com/ifish/enums/PushTypeEnum.java @@ -0,0 +1,33 @@ +package com.ifish.enums; + +public enum PushTypeEnum { + remove_device("remove_device","解除设备"), + wendu_warn("wendu_warn","温度报警"), + qu_reply("qu_reply","问题反馈"), + app_update("app_update","IOS更新推送"), + remind_water("remind_water","换水提醒"), + offline_push("offline_push","设备离线推送"); + + private PushTypeEnum(String key,String value){ + this.key = key; + this.value = value; + } + + private String key; + private String value; + + + public String getKey() { + return key; + } + public void setKey(String key) { + this.key = key; + } + public String getValue() { + return value; + } + public void setValue(String value) { + this.value = value; + } + +} diff --git a/src/main/java/com/ifish/job/job.java b/src/main/java/com/ifish/job/job.java new file mode 100644 index 0000000..dc68569 --- /dev/null +++ b/src/main/java/com/ifish/job/job.java @@ -0,0 +1,170 @@ +package com.ifish.job; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import net.sf.json.JSONArray; + +import org.springframework.beans.factory.annotation.Autowired; + +import com.ifish.enums.PhoneTypeEnum; +import com.ifish.jpush.JPushNotification; +import com.ifish.netease.NeteaseIM; +import com.ifish.util.IfishUtil; + +public class job{ + @Autowired + private NeteaseIM neteaseIM; + @Autowired + private JPushNotification jPushNotification2; + + private Connection connection = null; + private Statement stmt = null; + private PreparedStatement prest = null; + + /** + * 查询需要推送的用户并且推送完修改为下一次提醒日期 + */ + public void pushRemind(){ + System.out.println(new Date()+"开始任务"); + try { + Class.forName("com.mysql.jdbc.Driver"); + connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/myfishdb?characterEncoding=UTF-8", "ifish", "ifish7pwd"); + stmt = connection.createStatement(); + prest = connection.prepareStatement("update tbl_tmp_push_remind set is_push=? where user_id=? and device_id=?"); + } catch (SQLException e) { + e.printStackTrace(); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + //结果集 + ResultSet result = null; + try { + //推送提醒数 + int rowCount = 0; + //按分页来获取数据 + int pageNo = 0; + //云信限制每次最多500条 + int pageSize = 500; + //查询总共需要推送的用户数 + String countSql = "select count(1) as countRow from tbl_tmp_push_remind where is_push='0'"; + result = stmt.executeQuery(countSql); + if(result.next()){ + rowCount=result.getInt("countRow"); + pageNo = (rowCount+pageSize-1)/pageSize; + } + System.out.println(pageNo); + for (int i = 0; i < pageNo; i++) { + result = stmt.executeQuery("select device_id,user_id,show_name,login_type from tbl_tmp_push_remind where is_push='0' limit 0,"+pageSize); + //推送的用户 + List androidUser = new ArrayList(); + List iosUser = new ArrayList(); + List ids = new ArrayList(); + //更新提醒过的用户 + while(result.next()){ + Integer deviceId= result.getInt("device_id"); + Integer userId = result.getInt("user_id"); + String loginType = result.getString("login_type"); + prest.setString(1, "1"); + prest.setInt(2, userId); + prest.setInt(3, deviceId); + prest.addBatch(); + //云信 + ids.add(userId.toString()); + //极光 + if(loginType.toLowerCase().equals(PhoneTypeEnum.android.getKey())){ + androidUser.add(userId.toString()); + } + else if(loginType.toLowerCase().equals(PhoneTypeEnum.ios.getKey())){ + iosUser.add(userId.toString()); + } + } + //发送云信消息 + if(ids.size()>0){ + neteaseIM.sendBatchMsg("ifish", JSONArray.fromObject(ids).toString(), "【换水提醒】您的水族箱需要换水啦~您可以在水箱设置中更改提醒设置"); + } + //极光推送 + Integer iosSize = iosUser.size(); + Integer androidSize = androidUser.size(); + if(iosSize>0){ + push(PhoneTypeEnum.ios,iosUser.toArray(new String[iosSize])); + } + if(androidSize>0){ + push(PhoneTypeEnum.android,androidUser.toArray(new String[androidSize])); + } + //批量提交 + prest.executeBatch(); + //云信一分钟访问不超过120次 + Thread.sleep(600); + } + } catch (Exception e) { + e.printStackTrace(); + } + finally{ + if(result!=null){ + try { + result.close(); + result = null; + } catch (SQLException e) { + e.printStackTrace(); + } + } + if(stmt!=null){ + try { + stmt.close(); + stmt = null; + } catch (SQLException e) { + e.printStackTrace(); + } + } + if(prest!=null){ + try { + prest.close(); + prest = null; + } catch (SQLException e) { + e.printStackTrace(); + } + } + if(connection!=null){ + try { + connection.close(); + connection = null; + } catch (SQLException e) { + e.printStackTrace(); + } + } + } + } + /** + * 推送提醒 + * @param type + * @param ids + */ + public void push(PhoneTypeEnum type,String[] ids){ + try { + Map map = new HashMap(); + map.put("timestamp", IfishUtil.format2(new Date())); + //推送android + /*if(type.equals(PhoneTypeEnum.android)){ + System.out.println(new Date()+"android推送"+ids.length+"个"); + jPushNotification.sendAndroidNotification(ids, "换水提醒", "您的水族箱需要换水啦~您可以在水箱设置中更改提醒设置", map); + }*/ + //推送IOS + if(type.equals(PhoneTypeEnum.ios)){ + System.out.println(new Date()+"ios推送"+ids.length+"个"); + jPushNotification2.sendIosNotification(ids, "换水提醒", "您的水族箱需要换水啦~您可以在水箱设置中更改提醒设置", map); + } + } catch (Exception e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/ifish/jpush/JPushClient.java b/src/main/java/com/ifish/jpush/JPushClient.java new file mode 100644 index 0000000..61e4f57 --- /dev/null +++ b/src/main/java/com/ifish/jpush/JPushClient.java @@ -0,0 +1,807 @@ +package com.ifish.jpush; + +import java.util.Map; +import java.util.Set; + +import com.google.gson.JsonObject; +import com.ifish.jpush.common.ClientConfig; +import com.ifish.jpush.common.TimeUnit; +import com.ifish.jpush.common.Week; +import com.ifish.jpush.common.connection.HttpProxy; +import com.ifish.jpush.common.resp.APIConnectionException; +import com.ifish.jpush.common.resp.APIRequestException; +import com.ifish.jpush.common.resp.BooleanResult; +import com.ifish.jpush.common.resp.DefaultResult; +import com.ifish.jpush.device.AliasDeviceListResult; +import com.ifish.jpush.device.DeviceClient; +import com.ifish.jpush.device.OnlineStatus; +import com.ifish.jpush.device.TagAliasResult; +import com.ifish.jpush.device.TagListResult; +import com.ifish.jpush.push.PushClient; +import com.ifish.jpush.push.PushResult; +import com.ifish.jpush.push.model.Message; +import com.ifish.jpush.push.model.Platform; +import com.ifish.jpush.push.model.PushPayload; +import com.ifish.jpush.push.model.audience.Audience; +import com.ifish.jpush.push.model.notification.IosAlert; +import com.ifish.jpush.push.model.notification.Notification; +import com.ifish.jpush.report.MessagesResult; +import com.ifish.jpush.report.ReceivedsResult; +import com.ifish.jpush.report.ReportClient; +import com.ifish.jpush.report.UsersResult; +import com.ifish.jpush.schedule.ScheduleClient; +import com.ifish.jpush.schedule.ScheduleListResult; +import com.ifish.jpush.schedule.ScheduleResult; +import com.ifish.jpush.schedule.model.SchedulePayload; +import com.ifish.jpush.schedule.model.TriggerPayload; +import com.ifish.jpush.utils.Preconditions; + + +/** + * The global entrance of JPush API library. + */ +public class JPushClient { + private final PushClient _pushClient; + private final ReportClient _reportClient; + private final DeviceClient _deviceClient; + private final ScheduleClient _scheduleClient; + + /** + * Create a JPush Client. + * + * @param masterSecret API access secret of the appKey. + * @param appKey The KEY of one application on JPush. + */ + public JPushClient(String masterSecret, String appKey) { + _pushClient = new PushClient(masterSecret, appKey); + _reportClient = new ReportClient(masterSecret, appKey); + _deviceClient = new DeviceClient(masterSecret, appKey); + _scheduleClient = new ScheduleClient(masterSecret, appKey); + } + + public JPushClient(String masterSecret, String appKey, int maxRetryTimes) { + _pushClient = new PushClient(masterSecret, appKey, maxRetryTimes); + _reportClient = new ReportClient(masterSecret, appKey, maxRetryTimes); + _deviceClient = new DeviceClient(masterSecret, appKey, maxRetryTimes); + _scheduleClient = new ScheduleClient(masterSecret, appKey, maxRetryTimes); + } + + public JPushClient(String masterSecret, String appKey, int maxRetryTimes, HttpProxy proxy) { + _pushClient = new PushClient(masterSecret, appKey, maxRetryTimes, proxy); + _reportClient = new ReportClient(masterSecret, appKey, maxRetryTimes, proxy); + _deviceClient = new DeviceClient(masterSecret, appKey, maxRetryTimes, proxy); + _scheduleClient = new ScheduleClient(masterSecret, appKey, maxRetryTimes, proxy); + } + + /** + * Create a JPush Client by custom Client configuration. + * + * If you are using JPush privacy cloud, maybe this constructor is what you needed. + * + * @param masterSecret API access secret of the appKey. + * @param appKey The KEY of one application on JPush. + * @param maxRetryTimes Client request retry times. + * @param proxy The proxy, if there is no proxy, should be null. + * @param conf The client configuration. Can use ClientConfig.getInstance() as default. + */ + public JPushClient(String masterSecret, String appKey, int maxRetryTimes, HttpProxy proxy, ClientConfig conf) { + _pushClient = new PushClient(masterSecret, appKey, maxRetryTimes, proxy, conf); + _reportClient = new ReportClient(masterSecret, appKey, maxRetryTimes, proxy, conf); + _deviceClient = new DeviceClient(masterSecret, appKey, maxRetryTimes, proxy, conf); + _scheduleClient = new ScheduleClient(masterSecret, appKey, maxRetryTimes, proxy, conf); + } + + /** + * Create a JPush Client by custom Client configuration with global settings. + * + * If you are using JPush privacy cloud, and you want different settings from default globally, + * maybe this constructor is what you needed. + * + * @param masterSecret API access secret of the appKey. + * @param appKey The KEY of one application on JPush. + * @param maxRetryTimes Client request retry times. + * @param proxy The proxy, if there is no proxy, should be null. + * @param conf The client configuration. Can use ClientConfig.getInstance() as default. + * @param apnsProduction Global APNs environment setting. It will override PushPayload Options. + * @param timeToLive Global time_to_live setting. It will override PushPayload Options. + */ + public JPushClient(String masterSecret, String appKey, int maxRetryTimes, HttpProxy proxy, ClientConfig conf, + boolean apnsProduction, long timeToLive) { + _pushClient = new PushClient(masterSecret, appKey, maxRetryTimes, proxy, conf); + _reportClient = new ReportClient(masterSecret, appKey, maxRetryTimes, proxy, conf); + _deviceClient = new DeviceClient(masterSecret, appKey, maxRetryTimes, proxy, conf); + _scheduleClient = new ScheduleClient(masterSecret, appKey, maxRetryTimes, proxy, conf); + _pushClient.setDefaults(apnsProduction, timeToLive); + } + + /** + * Create a JPush Client with global settings. + * + * If you want different settings from default globally, this constructor is what you needed. + * + * @param masterSecret API access secret of the appKey. + * @param appKey The KEY of one application on JPush. + * @param apnsProduction Global APNs environment setting. It will override PushPayload Options. + * @param timeToLive Global time_to_live setting. It will override PushPayload Options. + */ + public JPushClient(String masterSecret, String appKey, boolean apnsProduction, long timeToLive) { + _pushClient = new PushClient(masterSecret, appKey, apnsProduction, timeToLive); + _reportClient = new ReportClient(masterSecret, appKey); + _deviceClient = new DeviceClient(masterSecret, appKey); + _scheduleClient = new ScheduleClient(masterSecret, appKey); + } + + + // ----------------------------- Push API + + /** + * Send a push with PushPayload object. + * + * @param pushPayload payload object of a push. + * @return PushResult The result object of a Push. Can be printed to a JSON. + * @throws APIConnectionException + * @throws APIRequestException + */ + public PushResult sendPush(PushPayload pushPayload) throws APIConnectionException, APIRequestException { + return _pushClient.sendPush(pushPayload); + } + + /** + * Send a push with JSON string. + * + * You can send a push JSON string directly with this method. + * + * Attention: globally settings cannot be affect this type of Push. + * + * @param payloadString payload of a push. + * @return PushResult. Can be printed to a JSON. + * @throws APIConnectionException + * @throws APIRequestException + */ + public PushResult sendPush(String payloadString) throws APIConnectionException, APIRequestException { + return _pushClient.sendPush(payloadString); + } + + /** + * Validate a push action, but do NOT send it actually. + * + * @param paylaod + * @return + * @throws APIConnectionException + * @throws APIRequestException + */ + public PushResult sendPushValidate(PushPayload paylaod) throws APIConnectionException, APIRequestException { + return _pushClient.sendPushValidate(paylaod); + } + + public PushResult sendPushValidate(String payloadString) throws APIConnectionException, APIRequestException { + return _pushClient.sendPushValidate(payloadString); + } + + + // ------------------------------- Report API + + /** + * Get received report. + * + * @param msgIds 100 msgids to batch getting is supported. + * @return ReceivedResult. Can be printed to JSON. + * @throws APIConnectionException + * @throws APIRequestException + */ + public ReceivedsResult getReportReceiveds(String msgIds) throws APIConnectionException, APIRequestException { + return _reportClient.getReceiveds(msgIds); + } + + public UsersResult getReportUsers(TimeUnit timeUnit, String start, int duration) throws APIConnectionException, APIRequestException { + return _reportClient.getUsers(timeUnit, start, duration); + } + + public MessagesResult getReportMessages(String msgIds) throws APIConnectionException, APIRequestException { + return _reportClient.getMessages(msgIds); + } + + + // ------------------------------ Shortcuts - notification + + /** + * Shortcut + */ + public PushResult sendNotificationAll(String alert) throws APIConnectionException, APIRequestException { + PushPayload payload = PushPayload.alertAll(alert); + return _pushClient.sendPush(payload); + } + + /** + * Shortcut + */ + public PushResult sendAndroidNotificationWithAlias(String title, String alert, + Map extras, String... alias) + throws APIConnectionException, APIRequestException { + PushPayload payload = PushPayload.newBuilder() + .setPlatform(Platform.android()) + .setAudience(Audience.alias(alias)) + .setNotification(Notification.android(alert, title, extras)) + .build(); + return _pushClient.sendPush(payload); + } + + /** + * Shortcut + */ + public PushResult sendAndroidNotificationWithRegistrationID(String title, String alert, + Map extras, String... registrationID) + throws APIConnectionException, APIRequestException { + PushPayload payload = PushPayload.newBuilder() + .setPlatform(Platform.android()) + .setAudience(Audience.registrationId(registrationID)) + .setNotification(Notification.android(alert, title, extras)) + .build(); + return _pushClient.sendPush(payload); + } + + /** + * Shortcut + */ + public PushResult sendIosNotificationWithAlias(String alert, Map extras, String... alias) + throws APIConnectionException, APIRequestException { + PushPayload payload = PushPayload.newBuilder() + .setPlatform(Platform.ios()) + .setAudience(Audience.alias(alias)) + .setNotification(Notification.ios(alert, extras)) + .build(); + return _pushClient.sendPush(payload); + } + + /** + * Send an iOS notification with alias. + * If you want to send alert as a Json object, maybe this method is what you needed. + * + * @param alert The wrapper of APNs alert. + * @param extras The extra params. + * @param alias The alias list. + * @return + * @throws APIConnectionException + * @throws APIRequestException + */ + public PushResult sendIosNotificationWithAlias(IosAlert alert, Map extras, String... alias) + throws APIConnectionException, APIRequestException { + PushPayload payload = PushPayload.newBuilder() + .setPlatform(Platform.ios()) + .setAudience(Audience.alias(alias)) + .setNotification(Notification.ios(alert, extras)) + .build(); + return _pushClient.sendPush(payload); + } + + /** + * Send an iOS notification with alias. + * If you want to send alert as a Json object, maybe this method is what you needed. + * + * @param alert The wrapper of APNs alert. + * @param extras The extra params. + * @param alias The alias list. + * @return + * @throws APIConnectionException + * @throws APIRequestException + */ + public PushResult sendIosNotificationWithAlias(JsonObject alert, Map extras, String... alias) + throws APIConnectionException, APIRequestException { + PushPayload payload = PushPayload.newBuilder() + .setPlatform(Platform.ios()) + .setAudience(Audience.alias(alias)) + .setNotification(Notification.ios(alert, extras)) + .build(); + return _pushClient.sendPush(payload); + } + + /** + * Shortcut + */ + public PushResult sendIosNotificationWithRegistrationID(String alert, + Map extras, String... registrationID) + throws APIConnectionException, APIRequestException { + PushPayload payload = PushPayload.newBuilder() + .setPlatform(Platform.ios()) + .setAudience(Audience.registrationId(registrationID)) + .setNotification(Notification.ios(alert, extras)) + .build(); + return _pushClient.sendPush(payload); + } + + /** + * Send an iOS notification with registrationIds. + * If you want to send alert as a Json object, maybe this method is what you needed. + * + * @param alert The wrapper of APNs alert. + * @param extras The extra params. + * @param registrationID The registration ids. + * @return + * @throws APIConnectionException + * @throws APIRequestException + */ + public PushResult sendIosNotificationWithRegistrationID(IosAlert alert, + Map extras, String... registrationID) + throws APIConnectionException, APIRequestException { + PushPayload payload = PushPayload.newBuilder() + .setPlatform(Platform.ios()) + .setAudience(Audience.registrationId(registrationID)) + .setNotification(Notification.ios(alert, extras)) + .build(); + return _pushClient.sendPush(payload); + } + + /** + * Send an iOS notification with registrationIds. + * If you want to send alert as a Json object, maybe this method is what you needed. + * + * @param alert The wrapper of APNs alert. + * @param extras The extra params. + * @param registrationID The registration ids. + * @return + * @throws APIConnectionException + * @throws APIRequestException + */ + public PushResult sendIosNotificationWithRegistrationID(JsonObject alert, + Map extras, String... registrationID) + throws APIConnectionException, APIRequestException { + PushPayload payload = PushPayload.newBuilder() + .setPlatform(Platform.ios()) + .setAudience(Audience.registrationId(registrationID)) + .setNotification(Notification.ios(alert, extras)) + .build(); + return _pushClient.sendPush(payload); + } + + + // ---------------------- shortcuts - message + + /** + * Shortcut + */ + public PushResult sendMessageAll(String msgContent) throws APIConnectionException, APIRequestException { + PushPayload payload = PushPayload.messageAll(msgContent); + return _pushClient.sendPush(payload); + } + + /** + * Shortcut + */ + public PushResult sendAndroidMessageWithAlias(String title, String msgContent, String... alias) + throws APIConnectionException, APIRequestException { + PushPayload payload = PushPayload.newBuilder() + .setPlatform(Platform.android()) + .setAudience(Audience.alias(alias)) + .setMessage(Message.newBuilder() + .setTitle(title) + .setMsgContent(msgContent) + .build()) + .build(); + return _pushClient.sendPush(payload); + } + + /** + * Shortcut + */ + public PushResult sendAndroidMessageWithRegistrationID(String title, String msgContent, String... registrationID) + throws APIConnectionException, APIRequestException { + PushPayload payload = PushPayload.newBuilder() + .setPlatform(Platform.android()) + .setAudience(Audience.registrationId(registrationID)) + .setMessage(Message.newBuilder() + .setTitle(title) + .setMsgContent(msgContent) + .build()) + .build(); + return _pushClient.sendPush(payload); + } + + /** + * Shortcut + */ + public PushResult sendIosMessageWithAlias(String title, String msgContent, String... alias) + throws APIConnectionException, APIRequestException { + PushPayload payload = PushPayload.newBuilder() + .setPlatform(Platform.ios()) + .setAudience(Audience.alias(alias)) + .setMessage(Message.newBuilder() + .setTitle(title) + .setMsgContent(msgContent) + .build()) + .build(); + return _pushClient.sendPush(payload); + } + + /** + * Shortcut + */ + public PushResult sendIosMessageWithRegistrationID(String title, String msgContent, String... registrationID) + throws APIConnectionException, APIRequestException { + PushPayload payload = PushPayload.newBuilder() + .setPlatform(Platform.ios()) + .setAudience(Audience.registrationId(registrationID)) + .setMessage(Message.newBuilder() + .setTitle(title) + .setMsgContent(msgContent) + .build()) + .build(); + return _pushClient.sendPush(payload); + } + + /** + * Shortcut + */ + public PushResult sendMessageWithRegistrationID(String title, String msgContent, String... registrationID) + throws APIConnectionException, APIRequestException { + PushPayload payload = PushPayload.newBuilder() + .setPlatform(Platform.all()) + .setAudience(Audience.registrationId(registrationID)) + .setMessage(Message.newBuilder() + .setTitle(title) + .setMsgContent(msgContent) + .build()) + .build(); + return _pushClient.sendPush(payload); + } + + + + // ----------------------- Device + + public TagAliasResult getDeviceTagAlias(String registrationId) + throws APIConnectionException, APIRequestException { + return _deviceClient.getDeviceTagAlias(registrationId); + } + + public DefaultResult updateDeviceTagAlias(String registrationId, boolean clearAlias, boolean clearTag) + throws APIConnectionException, APIRequestException { + return _deviceClient.updateDeviceTagAlias(registrationId, clearAlias, clearTag); + } + + public DefaultResult updateDeviceTagAlias(String registrationId, String alias, + Set tagsToAdd, Set tagsToRemove) + throws APIConnectionException, APIRequestException { + return _deviceClient.updateDeviceTagAlias(registrationId, alias, tagsToAdd, tagsToRemove); + } + + public TagListResult getTagList() + throws APIConnectionException, APIRequestException { + return _deviceClient.getTagList(); + } + + public BooleanResult isDeviceInTag(String theTag, String registrationID) + throws APIConnectionException, APIRequestException { + return _deviceClient.isDeviceInTag(theTag, registrationID); + } + + public DefaultResult addRemoveDevicesFromTag(String theTag, + Set toAddUsers, Set toRemoveUsers) + throws APIConnectionException, APIRequestException { + return _deviceClient.addRemoveDevicesFromTag(theTag, toAddUsers, + toRemoveUsers); + } + + public DefaultResult deleteTag(String theTag, String platform) + throws APIConnectionException, APIRequestException { + return _deviceClient.deleteTag(theTag, platform); + } + + public AliasDeviceListResult getAliasDeviceList(String alias, + String platform) throws APIConnectionException, APIRequestException { + return _deviceClient.getAliasDeviceList(alias, platform); + } + + public DefaultResult deleteAlias(String alias, String platform) + throws APIConnectionException, APIRequestException { + return _deviceClient.deleteAlias(alias, platform); + } + + public Map getUserOnlineStatus(String... registrationIds) + throws APIConnectionException, APIRequestException + { + return _deviceClient.getUserOnlineStatus(registrationIds); + } + + // ----------------------- Schedule + + /** + * Create a single schedule. + * @param name The schedule name. + * @param time The push time, format is 'yyyy-MM-dd HH:mm:ss' + * @param push The push payload. + * @return The created scheduleResult instance. + * @throws APIConnectionException + * @throws APIRequestException + */ + public ScheduleResult createSingleSchedule(String name, String time, PushPayload push) + throws APIConnectionException, APIRequestException { + TriggerPayload trigger = TriggerPayload.newBuilder() + .setSingleTime(time) + .buildSingle(); + SchedulePayload payload = SchedulePayload.newBuilder() + .setName(name) + .setEnabled(true) + .setTrigger(trigger) + .setPush(push) + .build(); + + return _scheduleClient.createSchedule(payload); + } + + /** + * Create a daily schedule push everyday. + * @param name The schedule name. + * @param start The schedule comes into effect date, format 'yyyy-MM-dd HH:mm:ss'. + * @param end The schedule expiration date, format 'yyyy-MM-dd HH:mm:ss'. + * @param time The push time, format 'HH:mm:ss' + * @param push The push payload. + * @return The created scheduleResult instance. + * @throws APIConnectionException + * @throws APIRequestException + */ + public ScheduleResult createDailySchedule(String name, String start, String end, String time, PushPayload push) + throws APIConnectionException, APIRequestException { + return createPeriodicalSchedule(name, start, end, time, TimeUnit.DAY, 1, null, push); + } + + /** + * Create a daily schedule push with a custom frequency. + * @param name The schedule name. + * @param start The schedule comes into effect date, format 'yyyy-MM-dd HH:mm:ss'. + * @param end The schedule expiration date, format 'yyyy-MM-dd HH:mm:ss'. + * @param time The push time, format 'HH:mm:ss' + * @param frequency The custom frequency. + * @param push The push payload. + * @return The created scheduleResult instance. + * @throws APIConnectionException + * @throws APIRequestException + */ + public ScheduleResult createDailySchedule(String name, String start, String end, String time, int frequency, PushPayload push) + throws APIConnectionException, APIRequestException { + return createPeriodicalSchedule(name, start, end, time, TimeUnit.DAY, frequency, null, push); + } + + /** + * Create a weekly schedule push every week at the appointed days. + * @param name The schedule name. + * @param start The schedule comes into effect date, format 'yyyy-MM-dd HH:mm:ss'. + * @param end The schedule expiration date, format 'yyyy-MM-dd HH:mm:ss'. + * @param time The push time, format 'HH:mm:ss' + * @param days The appointed days. + * @param push The push payload. + * @return The created scheduleResult instance. + * @throws APIConnectionException + * @throws APIRequestException + */ + public ScheduleResult createWeeklySchedule(String name, String start, String end, String time, Week[] days, PushPayload push) + throws APIConnectionException, APIRequestException { + Preconditions.checkArgument(null != days && days.length > 0, "The days must not be empty."); + + String[] points = new String[days.length]; + for(int i = 0 ; i < days.length; i++) { + points[i] = days[i].name(); + } + return createPeriodicalSchedule(name, start, end, time, TimeUnit.WEEK, 1, points, push); + } + + /** + * Create a weekly schedule push with a custom frequency at the appointed days. + * @param name The schedule name. + * @param start The schedule comes into effect date, format 'yyyy-MM-dd HH:mm:ss'. + * @param end The schedule expiration date, format 'yyyy-MM-dd HH:mm:ss'. + * @param time The push time, format 'HH:mm:ss'. + * @param frequency The custom frequency. + * @param days The appointed days. + * @param push The push payload. + * @return The created scheduleResult instance. + * @throws APIConnectionException + * @throws APIRequestException + */ + public ScheduleResult createWeeklySchedule(String name, String start, String end, String time, int frequency, Week[] days, PushPayload push) + throws APIConnectionException, APIRequestException { + Preconditions.checkArgument(null != days && days.length > 0, "The days must not be empty."); + + String[] points = new String[days.length]; + for(int i = 0 ; i < days.length; i++) { + points[i] = days[i].name(); + } + return createPeriodicalSchedule(name, start, end, time, TimeUnit.WEEK, frequency, points, push); + } + + /** + * Create a monthly schedule push every month at the appointed days. + * @param name The schedule name. + * @param start The schedule comes into effect date, format 'yyyy-MM-dd HH:mm:ss'. + * @param end The schedule expiration date, format 'yyyy-MM-dd HH:mm:ss'. + * @param time The push time, format 'HH:mm:ss'. + * @param points The appointed days. + * @param push The push payload. + * @return The created scheduleResult instance. + * @throws APIConnectionException + * @throws APIRequestException + */ + public ScheduleResult createMonthlySchedule(String name, String start, String end, String time, String[] points, PushPayload push) + throws APIConnectionException, APIRequestException { + Preconditions.checkArgument(null != points && points.length > 0, "The points must not be empty."); + return createPeriodicalSchedule(name, start, end, time, TimeUnit.MONTH, 1, points, push); + } + + /** + * Create a monthly schedule push with a custom frequency at the appointed days. + * @param name The schedule name. + * @param start The schedule comes into effect date, format 'yyyy-MM-dd HH:mm:ss'. + * @param end The schedule expiration date, format 'yyyy-MM-dd HH:mm:ss'. + * @param time The push time, format 'HH:mm:ss'. + * @param frequency The custom frequency. + * @param points The appointed days. + * @param push The push payload. + * @return The created scheduleResult instance. + * @throws APIConnectionException + * @throws APIRequestException + */ + public ScheduleResult createMonthlySchedule(String name, String start, String end, String time, int frequency, String[] points, PushPayload push) + throws APIConnectionException, APIRequestException { + Preconditions.checkArgument(null != points && points.length > 0, "The points must not be empty."); + return createPeriodicalSchedule(name, start, end, time, TimeUnit.MONTH, frequency, points, push); + } + + /** + * Get the schedule information by the schedule id. + * @param scheduleId The schedule id. + * @return The schedule information. + * @throws APIConnectionException + * @throws APIRequestException + */ + public ScheduleResult getSchedule(String scheduleId) + throws APIConnectionException, APIRequestException { + return _scheduleClient.getSchedule(scheduleId); + } + + /** + * Get the schedule list size and the first page. + * @return The schedule list size and the first page. + * @throws APIConnectionException + * @throws APIRequestException + */ + public ScheduleListResult getScheduleList() + throws APIConnectionException, APIRequestException { + return _scheduleClient.getScheduleList(1); + } + + /** + * Get the schedule list by the page. + * @param page The page to search. + * @return The schedule list of the appointed page. + * @throws APIConnectionException + * @throws APIRequestException + */ + public ScheduleListResult getScheduleList(int page) + throws APIConnectionException, APIRequestException { + return _scheduleClient.getScheduleList(page); + } + + /** + * Update the schedule name + * @param scheduleId The schedule id. + * @param name The new name. + * @return The schedule information after updated. + * @throws APIConnectionException + * @throws APIRequestException + */ + public ScheduleResult updateScheduleName(String scheduleId, String name) + throws APIConnectionException, APIRequestException { + SchedulePayload payload = SchedulePayload.newBuilder() + .setName(name) + .build(); + + return updateSchedule(scheduleId, payload); + } + + /** + * Enable the schedule. + * @param scheduleId The schedule id. + * @return The schedule information after updated. + * @throws APIConnectionException + * @throws APIRequestException + */ + public ScheduleResult enableSchedule(String scheduleId) + throws APIConnectionException, APIRequestException { + SchedulePayload payload = SchedulePayload.newBuilder() + .setEnabled(true) + .build(); + + return updateSchedule(scheduleId, payload); + } + + /** + * Disable the schedule. + * @param scheduleId The schedule id. + * @return The schedule information after updated. + * @throws APIConnectionException + * @throws APIRequestException + */ + public ScheduleResult disableSchedule(String scheduleId) + throws APIConnectionException, APIRequestException { + SchedulePayload payload = SchedulePayload.newBuilder() + .setEnabled(false) + .build(); + return updateSchedule(scheduleId, payload); + } + + /** + * Update the trigger of the schedule. + * @param scheduleId The schedule id. + * @param trigger The new trigger. + * @return The schedule information after updated. + * @throws APIConnectionException + * @throws APIRequestException + */ + public ScheduleResult updateScheduleTrigger(String scheduleId, TriggerPayload trigger) + throws APIConnectionException, APIRequestException { + SchedulePayload payload = SchedulePayload.newBuilder() + .setTrigger(trigger) + .build(); + + return updateSchedule(scheduleId, payload); + } + + /** + * Update the push content of the schedule. + * @param scheduleId The schedule id. + * @param push The new push payload. + * @return The schedule information after updated. + * @throws APIConnectionException + * @throws APIRequestException + */ + public ScheduleResult updateSchedulePush(String scheduleId, PushPayload push) + throws APIConnectionException, APIRequestException { + SchedulePayload payload = SchedulePayload.newBuilder() + .setPush(push) + .build(); + + return updateSchedule(scheduleId, payload); + } + + /** + * Update a schedule by the id. + * @param scheduleId The schedule id to update. + * @param payload The new schedule payload. + * @return The new schedule information. + * @throws APIConnectionException + * @throws APIRequestException + */ + public ScheduleResult updateSchedule(String scheduleId, SchedulePayload payload) + throws APIConnectionException, APIRequestException { + return _scheduleClient.updateSchedule(scheduleId, payload); + } + + /** + * Delete a schedule by id. + * @param scheduleId The schedule id. + * @throws APIConnectionException + * @throws APIRequestException + */ + public void deleteSchedule(String scheduleId) + throws APIConnectionException, APIRequestException { + _scheduleClient.deleteSchedule(scheduleId); + } + + private ScheduleResult createPeriodicalSchedule(String name, String start, String end, String time, + TimeUnit timeUnit, int frequency, String[] point, PushPayload push) + throws APIConnectionException, APIRequestException { + TriggerPayload trigger = TriggerPayload.newBuilder() + .setPeriodTime(start, end, time) + .setTimeFrequency(timeUnit, frequency, point ) + .buildPeriodical(); + SchedulePayload payload = SchedulePayload.newBuilder() + .setName(name) + .setEnabled(true) + .setTrigger(trigger) + .setPush(push) + .build(); + + return _scheduleClient.createSchedule(payload); + } + +} + diff --git a/src/main/java/com/ifish/jpush/JPushNotification.java b/src/main/java/com/ifish/jpush/JPushNotification.java new file mode 100644 index 0000000..8bdb565 --- /dev/null +++ b/src/main/java/com/ifish/jpush/JPushNotification.java @@ -0,0 +1,44 @@ +package com.ifish.jpush; + +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.JsonObject; +import com.ifish.jpush.common.resp.APIConnectionException; +import com.ifish.jpush.common.resp.APIRequestException; +import com.ifish.jpush.push.PushResult; + +public class JPushNotification { + + protected final Logger LOG = LoggerFactory.getLogger(JPushNotification.class); + JPushClient jpushClient = null; + + public JPushNotification(String appKey,String masterSecret,boolean productionModel){ + jpushClient = new JPushClient(masterSecret, appKey , productionModel ,86400); + } + + public void sendIosNotification(String[] alias,String title,String body,Map extras) { + try { + JsonObject json = new JsonObject(); + json.addProperty("title", title); + json.addProperty("body", body); + PushResult result = jpushClient.sendIosNotificationWithAlias(json, extras, alias); + } catch (APIConnectionException e) { + LOG.error("Connection error. Should retry later. ", e); + } catch (APIRequestException e) { + LOG.error("Error Message: " + e.getMessage()); + } + } + + /*public void sendAndroidNotification(String[] alias,String title,String alert,Map map) { + try { + PushResult result = jpushClient.sendAndroidNotificationWithAlias(title ,alert, map, alias); + } catch (APIConnectionException e) { + LOG.error("Connection error. Should retry later. ", e); + } catch (APIRequestException e) { + LOG.error("Error Message: " + e.getMessage()); + } + }*/ +} diff --git a/src/main/java/com/ifish/jpush/common/ClientConfig.java b/src/main/java/com/ifish/jpush/common/ClientConfig.java new file mode 100644 index 0000000..1a85939 --- /dev/null +++ b/src/main/java/com/ifish/jpush/common/ClientConfig.java @@ -0,0 +1,117 @@ +package com.ifish.jpush.common; + +import java.util.HashMap; +import java.util.Map; + +public class ClientConfig extends HashMap { + + private static ClientConfig instance = new ClientConfig(); + + public static final String DEVICE_HOST_NAME = "device.host.name"; + public static final Object DEVICE_HOST_NAME_SCHEMA = String.class; + + public static final String DEVICES_PATH = "devices.path"; + public static final Object DEVICES_PATH_SCHEMA = String.class; + + public static final String TAGS_PATH = "tags.path"; + public static final Object TAGS_PATH_SCHEMA = String.class; + + public static final String ALIASES_PATH = "aliases.path"; + public static final Object ALIASES_PATH_SCHEMA = String.class; + + public static final String PUSH_HOST_NAME = "push.host.name"; + public static final Object PUSH_HOST_NAME_SCHEMA = String.class; + + public static final String PUSH_PATH = "push.path"; + public static final Object PUSH_PATH_SCHEMA = String.class; + + public static final String PUSH_VALIDATE_PATH = "push.validate.path"; + public static final Object PUSH_VALIDATE_PATH_SCHMEA = String.class; + + public static final String REPORT_HOST_NAME = "report.host.name"; + public static final Object REPORT_HOST_NAME_SCHEMA = String.class; + + public static final String REPORT_RECEIVE_PATH = "report.receive.path"; + public static final Object REPORT_RECEIVE_PATH_SCHEMA = String.class; + + public static final String REPORT_USER_PATH = "report.user.path"; + public static final Object REPORT_USER_PATH_SCHEMA = String.class; + + public static final String REPORT_MESSAGE_PATH = "report.message.path"; + public static final Object REPORT_MESSAGE_PATH_SCHEMA = String.class; + + public static final String SCHEDULE_HOST_NAME = "schedule.host.name"; + public static final Object SCHEDULE_HOST_NAME_SCHEMA = String.class; + + public static final String SCHEDULE_PATH = "schedule.path"; + public static final Object SCHEDULE_PATH_SCHEMA = String.class; + + private ClientConfig() { + super(12); + this.put(DEVICE_HOST_NAME, "https://device.jpush.cn"); + this.put(DEVICES_PATH, "/v3/devices"); + this.put(TAGS_PATH, "/v3/tags"); + this.put(ALIASES_PATH, "/v3/aliases"); + + this.put(PUSH_HOST_NAME, "https://api.jpush.cn"); + this.put(PUSH_PATH, "/v3/push"); + this.put(PUSH_VALIDATE_PATH, "/v3/push/validate"); + + this.put(REPORT_HOST_NAME, "https://report.jpush.cn"); + this.put(REPORT_RECEIVE_PATH, "/v3/received"); + this.put(REPORT_USER_PATH, "/v3/users"); + this.put(REPORT_MESSAGE_PATH, "/v3/messages"); + + this.put(SCHEDULE_HOST_NAME, "https://api.jpush.cn"); + this.put(SCHEDULE_PATH, "/v3/schedules"); + } + + public static ClientConfig getInstance() { + return instance; + } + + public static void setDeviceHostName(Map conf, String hostName) { + conf.put(DEVICE_HOST_NAME, hostName); + } + + /** + * Setup custom device api host name, if using the JPush privacy cloud. + * @param hostName the custom api host name, default is JPush domain name + */ + public void setDeviceHostName(String hostName) { + setDeviceHostName(this, hostName); + } + + public static void setPushHostName(Map conf, String hostName) { + conf.put(PUSH_HOST_NAME, hostName); + } + + /** + * Setup custom push api host name, if using the JPush privacy cloud. + * @param hostName the custom api host name, default is JPush domain name + */ + public void setPushHostName(String hostName) { + setPushHostName(this, hostName); + } + + public static void setReportHostName(Map conf, String hostName) { + conf.put(REPORT_HOST_NAME, hostName); + } + + /** + * Setup custom report api host name, if using the JPush privacy cloud. + * @param hostName the custom api host name, default is JPush domain name + */ + public void setReportHostName(String hostName) { + setReportHostName(this, hostName); + } + + public static void setScheduleHostName(Map conf, String hostName) { + conf.put(SCHEDULE_HOST_NAME, hostName); + } + + public void setScheduleHostName(String hostName) { + setScheduleHostName(this, hostName); + } + +} diff --git a/src/main/java/com/ifish/jpush/common/DeviceType.java b/src/main/java/com/ifish/jpush/common/DeviceType.java new file mode 100644 index 0000000..0c8a455 --- /dev/null +++ b/src/main/java/com/ifish/jpush/common/DeviceType.java @@ -0,0 +1,19 @@ +package com.ifish.jpush.common; + +public enum DeviceType { + + Android("android"), + IOS("ios"), + WinPhone("winphone"); + + private final String value; + + private DeviceType(final String value) { + this.value = value; + } + + public String value() { + return this.value; + } + +} diff --git a/src/main/java/com/ifish/jpush/common/ServiceHelper.java b/src/main/java/com/ifish/jpush/common/ServiceHelper.java new file mode 100644 index 0000000..a67e5de --- /dev/null +++ b/src/main/java/com/ifish/jpush/common/ServiceHelper.java @@ -0,0 +1,93 @@ +package com.ifish.jpush.common; + +import java.text.SimpleDateFormat; +import java.util.Random; +import java.util.Set; +import java.util.regex.Pattern; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.JsonArray; +import com.google.gson.JsonPrimitive; +import com.ifish.jpush.utils.Base64; +import com.ifish.jpush.utils.StringUtils; + +public class ServiceHelper { + + private static final Logger LOG = LoggerFactory.getLogger(ServiceHelper.class); + private final static Pattern PUSH_PATTERNS = Pattern.compile("[^a-zA-Z0-9]"); + private final static String BASIC_PREFIX = "Basic"; + + private static final Random RANDOM = new Random(System.currentTimeMillis()); + private static final int MIN = 100000; + private static final int MAX = Integer.MAX_VALUE; + + private static final int MAX_BADGE_NUMBER = 99999; + + private static final Pattern USERNAME_PATTERN = Pattern.compile("^[a-zA-Z0-9][a-zA-Z_0-9.、。@,-]*"); + private static final Pattern DATE_PATTERN = Pattern.compile("[0-9]{4}-[0-9]{2}-[0-9]{2}"); + private static final String DATE_FORMAT = "yyyy-MM-dd"; + + + public static boolean isValidIntBadge(int intBadge) { + if (intBadge >= 0 && intBadge <= MAX_BADGE_NUMBER) { + return true; + } + return false; + } + + public static int generateSendno() { + return RANDOM.nextInt((MAX - MIN) + 1) + MIN; + } + + public static String getBasicAuthorization(String username, String password) { + String encodeKey = username + ":" + password; + return BASIC_PREFIX + " " + String.valueOf(Base64.encode(encodeKey.getBytes())); + } + + public static void checkBasic(String appKey, String masterSecret) { + if (StringUtils.isEmpty(appKey) + || StringUtils.isEmpty(masterSecret)) { + throw new IllegalArgumentException("appKey and masterSecret are both required."); + } + if (appKey.length() != 24 + || masterSecret.length() != 24 + || PUSH_PATTERNS.matcher(appKey).find() + || PUSH_PATTERNS.matcher(masterSecret).find()) { + throw new IllegalArgumentException("appKey and masterSecret format is incorrect. " + + "They should be 24 size, and be composed with alphabet and numbers. " + + "Please confirm that they are coming from JPush Web Portal."); + } + } + + public static JsonArray fromSet(Set sets) { + JsonArray array = new JsonArray(); + if (null != sets && sets.size() > 0) { + for (String item : sets) { + array.add(new JsonPrimitive(item)); + } + } + return array; + } + + public static boolean checkUsername(String username) { + return USERNAME_PATTERN.matcher(username).matches(); + } + + public static boolean isValidBirthday( String birthday) { + try { + if( ! DATE_PATTERN.matcher(birthday).matches() ) { + return false; + } + SimpleDateFormat format = new SimpleDateFormat(DATE_FORMAT); + format.setLenient(false); + format.parse(birthday); + } catch (Exception e) { + LOG.error("incorrect date format. " + birthday, e); + return false; + } + return true; + } + +} diff --git a/src/main/java/com/ifish/jpush/common/TimeUnit.java b/src/main/java/com/ifish/jpush/common/TimeUnit.java new file mode 100644 index 0000000..4df6d69 --- /dev/null +++ b/src/main/java/com/ifish/jpush/common/TimeUnit.java @@ -0,0 +1,10 @@ +package com.ifish.jpush.common; + +public enum TimeUnit { + + HOUR, + DAY, + MONTH, + WEEK + +} diff --git a/src/main/java/com/ifish/jpush/common/Week.java b/src/main/java/com/ifish/jpush/common/Week.java new file mode 100644 index 0000000..f37558d --- /dev/null +++ b/src/main/java/com/ifish/jpush/common/Week.java @@ -0,0 +1,11 @@ +package com.ifish.jpush.common; + +public enum Week { + MON, + TUE, + WED, + THU, + FRI, + SAT, + SUN +} diff --git a/src/main/java/com/ifish/jpush/common/connection/HttpProxy.java b/src/main/java/com/ifish/jpush/common/connection/HttpProxy.java new file mode 100644 index 0000000..f157947 --- /dev/null +++ b/src/main/java/com/ifish/jpush/common/connection/HttpProxy.java @@ -0,0 +1,61 @@ +package com.ifish.jpush.common.connection; + +import java.net.InetSocketAddress; +import java.net.Proxy; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.ifish.jpush.common.ServiceHelper; +import com.ifish.jpush.utils.Preconditions; + +public class HttpProxy { + private static final Logger LOG = LoggerFactory.getLogger(HttpProxy.class); + + private String host; + private int port; + private String username; + private String password; + + private boolean authenticationNeeded = false; + + public HttpProxy(String host, int port) { + this.host = host; + this.port = port; + } + + public HttpProxy(String host, int port, String username, String password) { + this(host, port); + + Preconditions.checkArgument(! (null == username), "username should not be null"); + Preconditions.checkArgument(! (null == password), "password should not be null"); + + this.username = username; + this.password = password; + authenticationNeeded = true; + + LOG.info("Http Proxy - host:" + host + ", port:" + port + + ", username:" + username + ", password:" + password); + } + + + public Proxy getNetProxy() { + return new Proxy(Proxy.Type.HTTP, new InetSocketAddress(host, port)); + } + + public boolean isAuthenticationNeeded() { + return this.authenticationNeeded; + } + + public String getProxyAuthorization() { + return ServiceHelper.getBasicAuthorization(username, password); + } + + public String getUsername() { + return this.username; + } + + public String getPassword() { + return this.password; + } +} diff --git a/src/main/java/com/ifish/jpush/common/connection/IHttpClient.java b/src/main/java/com/ifish/jpush/common/connection/IHttpClient.java new file mode 100644 index 0000000..bf774a3 --- /dev/null +++ b/src/main/java/com/ifish/jpush/common/connection/IHttpClient.java @@ -0,0 +1,68 @@ +package com.ifish.jpush.common.connection; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.ifish.jpush.common.resp.APIConnectionException; +import com.ifish.jpush.common.resp.APIRequestException; +import com.ifish.jpush.common.resp.ResponseWrapper; + +public interface IHttpClient { + + public static final String CHARSET = "UTF-8"; + public static final String CONTENT_TYPE_JSON = "application/json"; + public static final String CONTENT_TYPE_FORM = "application/x-www-form-urlencoded"; + + public static final String RATE_LIMIT_QUOTA = "X-Rate-Limit-Limit"; + public static final String RATE_LIMIT_Remaining = "X-Rate-Limit-Remaining"; + public static final String RATE_LIMIT_Reset = "X-Rate-Limit-Reset"; + public static final String JPUSH_USER_AGENT = "JPush-API-Java-Client"; + + public static final int RESPONSE_OK = 200; + + public enum RequestMethod { + GET, + POST, + PUT, + DELETE + } + + public static final String IO_ERROR_MESSAGE = "Connection IO error. \n" + + "Can not connect to JPush Server. " + + "Please ensure your internet connection is ok. \n" + + "If the problem persists, please let us know at support@jpush.cn."; + + public static final String CONNECT_TIMED_OUT_MESSAGE = "connect timed out. \n" + + "Connect to JPush Server timed out, and already retried some times. \n" + + "Please ensure your internet connection is ok. \n" + + "If the problem persists, please let us know at support@jpush.cn."; + + public static final String READ_TIMED_OUT_MESSAGE = "Read timed out. \n" + + "Read response from JPush Server timed out. \n" + + "If this is a Push action, you may not want to retry. \n" + + "It may be due to slowly response from JPush server, or unstable connection. \n" + + "If the problem persists, please let us know at support@jpush.cn."; + + public static Gson _gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create(); + + + //设置连接超时时间 + public static final int DEFAULT_CONNECTION_TIMEOUT = (5 * 1000); // milliseconds + + //设置读取超时时间 + public static final int DEFAULT_READ_TIMEOUT = (30 * 1000); // milliseconds + + public static final int DEFAULT_MAX_RETRY_TIMES = 3; + + public ResponseWrapper sendGet(String url) + throws APIConnectionException, APIRequestException; + + public ResponseWrapper sendDelete(String url) + throws APIConnectionException, APIRequestException; + + public ResponseWrapper sendPost(String url, String content) + throws APIConnectionException, APIRequestException; + + + public ResponseWrapper sendPut(String url, String content) + throws APIConnectionException, APIRequestException; +} diff --git a/src/main/java/com/ifish/jpush/common/connection/NativeHttpClient.java b/src/main/java/com/ifish/jpush/common/connection/NativeHttpClient.java new file mode 100644 index 0000000..15f0aee --- /dev/null +++ b/src/main/java/com/ifish/jpush/common/connection/NativeHttpClient.java @@ -0,0 +1,331 @@ +package com.ifish.jpush.common.connection; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.Authenticator; +import java.net.HttpURLConnection; +import java.net.PasswordAuthentication; +import java.net.SocketTimeoutException; +import java.net.URL; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSession; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.ifish.jpush.common.resp.APIConnectionException; +import com.ifish.jpush.common.resp.APIRequestException; +import com.ifish.jpush.common.resp.ResponseWrapper; + +/** + * The implementation has no connection pool mechanism, used origin java connection. + * + * 本实现没有连接池机制,基于 Java 原始的 HTTP 连接实现。 + * + * 遇到连接超时,会自动重连指定的次数(默认为 3);如果是读取超时,则不会自动重连。 + * + * 可选支持 HTTP 代理,同时支持 2 种方式:1) HTTP 头上加上 Proxy-Authorization 信息;2)全局配置 Authenticator.setDefault; + */ +public class NativeHttpClient implements IHttpClient { + private static final Logger LOG = LoggerFactory.getLogger(NativeHttpClient.class); + private static final String KEYWORDS_CONNECT_TIMED_OUT = "connect timed out"; + private static final String KEYWORDS_READ_TIMED_OUT = "Read timed out"; + + private int _maxRetryTimes = 0; + private String _authCode; + private HttpProxy _proxy; + + /** + * 默认的重连次数是 3 + */ + public NativeHttpClient(String authCode) { + this(authCode, DEFAULT_MAX_RETRY_TIMES, null); + } + + public NativeHttpClient(String authCode, int maxRetryTimes, HttpProxy proxy) { + this._maxRetryTimes = maxRetryTimes; + LOG.info("Created instance with _maxRetryTimes = " + _maxRetryTimes); + + this._authCode = authCode; + this._proxy = proxy; + + if ( null != _proxy && _proxy.isAuthenticationNeeded()) { + Authenticator.setDefault(new SimpleProxyAuthenticator( + _proxy.getUsername(), _proxy.getPassword())); + } + + initSSL(); + } + + public ResponseWrapper sendGet(String url) + throws APIConnectionException, APIRequestException { + return sendGet(url, null); + } + + public ResponseWrapper sendGet(String url, String content) + throws APIConnectionException, APIRequestException { + return doRequest(url, content, RequestMethod.GET); + } + + public ResponseWrapper sendDelete(String url) + throws APIConnectionException, APIRequestException { + return sendDelete(url, null); + } + + public ResponseWrapper sendDelete(String url, String content) + throws APIConnectionException, APIRequestException { + return doRequest(url, content, RequestMethod.DELETE); + } + + public ResponseWrapper sendPost(String url, String content) + throws APIConnectionException, APIRequestException { + return doRequest(url, content, RequestMethod.POST); + } + + public ResponseWrapper sendPut(String url, String content) + throws APIConnectionException, APIRequestException { + return doRequest(url, content, RequestMethod.PUT); + } + + public ResponseWrapper doRequest(String url, String content, + RequestMethod method) throws APIConnectionException, APIRequestException { + ResponseWrapper response = null; + for (int retryTimes = 0; ; retryTimes++) { + try { + response = _doRequest(url, content, method); + break; + } catch (SocketTimeoutException e) { + if (KEYWORDS_READ_TIMED_OUT.equals(e.getMessage())) { + // Read timed out. For push, maybe should not re-send. + throw new APIConnectionException(READ_TIMED_OUT_MESSAGE, e, true); + } else { // connect timed out + if (retryTimes >= _maxRetryTimes) { + throw new APIConnectionException(CONNECT_TIMED_OUT_MESSAGE, e, retryTimes); + } else { + LOG.debug("connect timed out - retry again - " + (retryTimes + 1)); + } + } + } + } + return response; + } + + private ResponseWrapper _doRequest(String url, String content, + RequestMethod method) throws APIConnectionException, APIRequestException, + SocketTimeoutException { + + LOG.debug("Send request - " + method.toString() + " "+ url); + if (null != content) { + LOG.debug("Request Content - " + content); + } + HttpURLConnection conn = null; + OutputStream out = null; + StringBuffer sb = new StringBuffer(); + ResponseWrapper wrapper = new ResponseWrapper(); + + try { + URL aUrl = new URL(url); + + if (null != _proxy) { + conn = (HttpURLConnection) aUrl.openConnection(_proxy.getNetProxy()); + if (_proxy.isAuthenticationNeeded()) { + conn.setRequestProperty("Proxy-Authorization", _proxy.getProxyAuthorization()); + } + } else { + conn = (HttpURLConnection) aUrl.openConnection(); + } + + conn.setConnectTimeout(DEFAULT_CONNECTION_TIMEOUT); + conn.setReadTimeout(DEFAULT_READ_TIMEOUT); + conn.setUseCaches(false); + conn.setRequestMethod(method.name()); + conn.setRequestProperty("User-Agent", JPUSH_USER_AGENT); + conn.setRequestProperty("Connection", "Keep-Alive"); + conn.setRequestProperty("Accept-Charset", CHARSET); + conn.setRequestProperty("Charset", CHARSET); + conn.setRequestProperty("Authorization", _authCode); + conn.setRequestProperty("Content-Type", CONTENT_TYPE_JSON); + + if(null == content) { + conn.setDoOutput(false); + } else { + conn.setDoOutput(true); + byte[] data = content.getBytes(CHARSET); + conn.setRequestProperty("Content-Length", String.valueOf(data.length)); + out = conn.getOutputStream(); + out.write(data); + out.flush(); + } + + int status = conn.getResponseCode(); + InputStream in = null; + if (status / 100 == 2) { + in = conn.getInputStream(); + } else { + in = conn.getErrorStream(); + } + + if (null != in) { + InputStreamReader reader = new InputStreamReader(in, CHARSET); + char[] buff = new char[1024]; + int len; + while ((len = reader.read(buff)) > 0) { + sb.append(buff, 0, len); + } + } + + String responseContent = sb.toString(); + wrapper.responseCode = status; + wrapper.responseContent = responseContent; + + String quota = conn.getHeaderField(RATE_LIMIT_QUOTA); + String remaining = conn.getHeaderField(RATE_LIMIT_Remaining); + String reset = conn.getHeaderField(RATE_LIMIT_Reset); + wrapper.setRateLimit(quota, remaining, reset); + + if (status >= 200 && status < 300) { + LOG.debug("Succeed to get response OK - responseCode:" + status); + LOG.debug("Response Content - " + responseContent); + + } else if (status >= 300 && status < 400) { + LOG.warn("Normal response but unexpected - responseCode:" + status + ", responseContent:" + responseContent); + + } else { + LOG.warn("Got error response - responseCode:" + status + ", responseContent:" + responseContent); + + switch (status) { + case 400: + LOG.error("Your request params is invalid. Please check them according to error message."); + wrapper.setErrorObject(); + break; + case 401: + LOG.error("Authentication failed! Please check authentication params according to docs."); + wrapper.setErrorObject(); + break; + case 403: + LOG.error("Request is forbidden! Maybe your appkey is listed in blacklist or your params is invalid."); + wrapper.setErrorObject(); + break; + case 404: + LOG.error("Request page is not found! Maybe your params is invalid."); + wrapper.setErrorObject(); + break; + case 410: + LOG.error("Request resource is no longer in service. Please according to notice on official website."); + wrapper.setErrorObject(); + case 429: + LOG.error("Too many requests! Please review your appkey's request quota."); + wrapper.setErrorObject(); + break; + case 500: + case 502: + case 503: + case 504: + LOG.error("Seems encountered server error. Maybe JPush is in maintenance? Please retry later."); + break; + default: + LOG.error("Unexpected response."); + } + + throw new APIRequestException(wrapper); + } + + } catch (SocketTimeoutException e) { + if (e.getMessage().contains(KEYWORDS_CONNECT_TIMED_OUT)) { + throw e; + } else if (e.getMessage().contains(KEYWORDS_READ_TIMED_OUT)) { + throw new SocketTimeoutException(KEYWORDS_READ_TIMED_OUT); + } + LOG.debug(IO_ERROR_MESSAGE, e); + throw new APIConnectionException(IO_ERROR_MESSAGE, e); + + } catch (IOException e) { + LOG.debug(IO_ERROR_MESSAGE, e); + throw new APIConnectionException(IO_ERROR_MESSAGE, e); + + } finally { + if (null != out) { + try { + out.close(); + } catch (IOException e) { + LOG.error("Failed to close stream.", e); + } + } + if (null != conn) { + conn.disconnect(); + } + } + + return wrapper; + } + + protected void initSSL() { + TrustManager[] tmCerts = new javax.net.ssl.TrustManager[1]; + tmCerts[0] = new SimpleTrustManager(); + try { + SSLContext sslContext = SSLContext.getInstance("SSL"); + sslContext.init(null, tmCerts, null); + HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory()); + + HostnameVerifier hostnameVerifier = new SimpleHostnameVerifier(); + HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier); + } catch (Exception e) { + LOG.error("Init SSL error", e); + } + } + + + private static class SimpleHostnameVerifier implements HostnameVerifier { + + @Override + public boolean verify(String hostname, SSLSession session) { + return true; + } + + } + + private static class SimpleTrustManager implements TrustManager, X509TrustManager { + + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) + throws CertificateException { + return; + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) + throws CertificateException { + return; + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return null; + } + } + + private static class SimpleProxyAuthenticator extends java.net.Authenticator { + private String username; + private String password; + + public SimpleProxyAuthenticator(String username, String password) { + this.username = username; + this.password = password; + } + + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication( + this.username, + this.password.toCharArray()); + } + } +} diff --git a/src/main/java/com/ifish/jpush/common/resp/APIConnectionException.java b/src/main/java/com/ifish/jpush/common/resp/APIConnectionException.java new file mode 100644 index 0000000..6ddb7e2 --- /dev/null +++ b/src/main/java/com/ifish/jpush/common/resp/APIConnectionException.java @@ -0,0 +1,40 @@ +package com.ifish.jpush.common.resp; + +/** + * Should retry for encountering this exception basically. + * Normally it is due to: + * 1. Connect timed out. + * 2. Read timed out. + * 3. Cannot parse domain. + * + * For Push action, if the exception is "Read timed out" you may not want to retry it. + */ +public class APIConnectionException extends Exception { + private static final long serialVersionUID = -2615370590441195647L; + private boolean readTimedout = false; + private int doneRetriedTimes = 0; + + public APIConnectionException(String message, Throwable e) { + super(message, e); + } + + public APIConnectionException(String message, Throwable e, int doneRetriedTimes) { + super(message, e); + this.doneRetriedTimes = doneRetriedTimes; + } + + public APIConnectionException(String message, Throwable e, boolean readTimedout) { + super(message, e); + this.readTimedout = readTimedout; + } + + public boolean isReadTimedout() { + return readTimedout; + } + + public int getDoneRetriedTimes() { + return this.doneRetriedTimes; + } +} + + diff --git a/src/main/java/com/ifish/jpush/common/resp/APIRequestException.java b/src/main/java/com/ifish/jpush/common/resp/APIRequestException.java new file mode 100644 index 0000000..635bfdd --- /dev/null +++ b/src/main/java/com/ifish/jpush/common/resp/APIRequestException.java @@ -0,0 +1,73 @@ +package com.ifish.jpush.common.resp; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.ifish.jpush.common.resp.ResponseWrapper.ErrorObject; + +public class APIRequestException extends Exception implements IRateLimiting { + private static final long serialVersionUID = -3921022835186996212L; + + protected static Gson _gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create(); + + private final ResponseWrapper responseWrapper; + + public APIRequestException(ResponseWrapper responseWrapper) { + super(responseWrapper.responseContent); + this.responseWrapper = responseWrapper; + } + + public int getStatus() { + return this.responseWrapper.responseCode; + } + + public long getMsgId() { + ErrorObject eo = getErrorObject(); + if (null != eo) { + return eo.msg_id; + } + return 0; + } + + public int getErrorCode() { + ErrorObject eo = getErrorObject(); + if (null != eo && null != eo.error) { + return eo.error.code; + } + return -1; + } + + public String getErrorMessage() { + ErrorObject eo = getErrorObject(); + if (null != eo && null != eo.error) { + return eo.error.message; + } + return null; + } + + @Override + public String toString() { + return _gson.toJson(this); + } + + private ErrorObject getErrorObject() { + return this.responseWrapper.error; + } + + + @Override + public int getRateLimitQuota() { + return responseWrapper.rateLimitQuota; + } + + @Override + public int getRateLimitRemaining() { + return responseWrapper.rateLimitRemaining; + } + + @Override + public int getRateLimitReset() { + return responseWrapper.rateLimitReset; + } + +} + diff --git a/src/main/java/com/ifish/jpush/common/resp/BaseResult.java b/src/main/java/com/ifish/jpush/common/resp/BaseResult.java new file mode 100644 index 0000000..58a425c --- /dev/null +++ b/src/main/java/com/ifish/jpush/common/resp/BaseResult.java @@ -0,0 +1,93 @@ +package com.ifish.jpush.common.resp; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +public abstract class BaseResult implements IRateLimiting { + public static final int ERROR_CODE_NONE = -1; + public static final int ERROR_CODE_OK = 0; + public static final String ERROR_MESSAGE_NONE = "None error message."; + + protected static final int RESPONSE_OK = 200; + protected static Gson _gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create(); + + private ResponseWrapper responseWrapper; + + public void setResponseWrapper(ResponseWrapper responseWrapper) { + this.responseWrapper = responseWrapper; + } + + public String getOriginalContent() { + if (null != responseWrapper) { + return responseWrapper.responseContent; + } + return null; + } + + public int getResponseCode() { + if(null != responseWrapper) { + return responseWrapper.responseCode; + } + return -1; + } + + public boolean isResultOK() { + if(null != responseWrapper) { + return ( responseWrapper.responseCode / 200 ) == 1; + } + return false; + } + + public static T fromResponse( + ResponseWrapper responseWrapper, Class clazz) { + T result = null; + + if (responseWrapper.isServerResponse()) { + result = _gson.fromJson(responseWrapper.responseContent, clazz); + } else { + try { + result = clazz.newInstance(); + } catch (InstantiationException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + if(result!=null){ + result.setResponseWrapper(responseWrapper); + } + return result; + } + + + @Override + public int getRateLimitQuota() { + if (null != responseWrapper) { + return responseWrapper.rateLimitQuota; + } + return 0; + } + + @Override + public int getRateLimitRemaining() { + if (null != responseWrapper) { + return responseWrapper.rateLimitRemaining; + } + return 0; + } + + @Override + public int getRateLimitReset() { + if (null != responseWrapper) { + return responseWrapper.rateLimitReset; + } + return 0; + } + + @Override + public String toString() { + return _gson.toJson(this); + } + + +} diff --git a/src/main/java/com/ifish/jpush/common/resp/BooleanResult.java b/src/main/java/com/ifish/jpush/common/resp/BooleanResult.java new file mode 100644 index 0000000..e2b3956 --- /dev/null +++ b/src/main/java/com/ifish/jpush/common/resp/BooleanResult.java @@ -0,0 +1,9 @@ +package com.ifish.jpush.common.resp; + +import com.google.gson.annotations.Expose; + +public class BooleanResult extends DefaultResult { + + @Expose public boolean result; + +} diff --git a/src/main/java/com/ifish/jpush/common/resp/DefaultResult.java b/src/main/java/com/ifish/jpush/common/resp/DefaultResult.java new file mode 100644 index 0000000..226a872 --- /dev/null +++ b/src/main/java/com/ifish/jpush/common/resp/DefaultResult.java @@ -0,0 +1,17 @@ +package com.ifish.jpush.common.resp; + +public class DefaultResult extends BaseResult { + + public static DefaultResult fromResponse(ResponseWrapper responseWrapper) { + DefaultResult result = null; + + if (responseWrapper.isServerResponse()) { + result = new DefaultResult(); + } + if(result!=null){ + result.setResponseWrapper(responseWrapper); + } + return result; + } + +} diff --git a/src/main/java/com/ifish/jpush/common/resp/IRateLimiting.java b/src/main/java/com/ifish/jpush/common/resp/IRateLimiting.java new file mode 100644 index 0000000..f5d9316 --- /dev/null +++ b/src/main/java/com/ifish/jpush/common/resp/IRateLimiting.java @@ -0,0 +1,12 @@ +package com.ifish.jpush.common.resp; + +public interface IRateLimiting { + + public int getRateLimitQuota(); + + public int getRateLimitRemaining(); + + public int getRateLimitReset(); + +} + diff --git a/src/main/java/com/ifish/jpush/common/resp/ResponseWrapper.java b/src/main/java/com/ifish/jpush/common/resp/ResponseWrapper.java new file mode 100644 index 0000000..e68c450 --- /dev/null +++ b/src/main/java/com/ifish/jpush/common/resp/ResponseWrapper.java @@ -0,0 +1,109 @@ +package com.ifish.jpush.common.resp; + +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.JsonSyntaxException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ResponseWrapper { + private static final Logger LOG = LoggerFactory.getLogger(ResponseWrapper.class); + private static final int RESPONSE_CODE_NONE = -1; + + private static Gson _gson = new Gson(); + private static JsonParser jsonParser = new JsonParser(); + + public int responseCode = RESPONSE_CODE_NONE; + public String responseContent; + + public ErrorObject error; // error for non-200 response, used by new API + + public int rateLimitQuota; + public int rateLimitRemaining; + public int rateLimitReset; + + public void setRateLimit(String quota, String remaining, String reset) { + if (null == quota) return; + + try { + rateLimitQuota = Integer.parseInt(quota); + rateLimitRemaining = Integer.parseInt(remaining); + rateLimitReset = Integer.parseInt(reset); + + LOG.debug("JPush API Rate Limiting params - quota:" + quota + ", remaining:" + remaining + ", reset:" + reset); + } catch (NumberFormatException e) { + LOG.debug("Unexpected - parse rate limiting headers error."); + } + } + + public void setErrorObject() { + error = new ErrorObject(); + error.error = new ErrorEntity(); + try { + JsonElement element = jsonParser.parse(responseContent); + JsonObject errorObj = null; + if( element instanceof JsonArray) { + JsonArray array = (JsonArray) element; + for(int i = 0; i < array.size(); i++) { + if(array.get(i).getAsJsonObject().has("error")) { + errorObj = array.get(i).getAsJsonObject(); + break; + } + } + } else if(element instanceof JsonObject) { + errorObj = (JsonObject) element; + } else { + // nothing + } + if(null != errorObj) { + JsonObject errorMsg = errorObj; + if(errorObj.has("msg_id")) { + error.msg_id = errorObj.get("msg_id").getAsLong(); + } + if (errorObj.has("error")) { + errorMsg = (JsonObject) errorObj.get("error"); + } + if(errorMsg.has("code")) { + error.error.code = errorMsg.get("code").getAsInt(); + } + if(errorMsg.has("message")) { + error.error.message = errorMsg.get("message").getAsString(); + } + } + } catch(JsonSyntaxException e) { + LOG.error("Unexpected - responseContent:" + responseContent, e); + } catch (Exception e) { + LOG.error("Unexpected - responseContent:" + responseContent, e); + } + } + + public boolean isServerResponse() { + if (responseCode / 100 == 2) return true; + if (responseCode > 0 && null != error && error.error.code > 0) return true; + return false; + } + + @Override + public String toString() { + return _gson.toJson(this); + } + + public static class ErrorObject { + public long msg_id; + public ErrorEntity error; + } + + public static class ErrorEntity { + public int code; + public String message; + + @Override + public String toString() { + return _gson.toJson(this); + } + } + +} diff --git a/src/main/java/com/ifish/jpush/device/AliasDeviceListResult.java b/src/main/java/com/ifish/jpush/device/AliasDeviceListResult.java new file mode 100644 index 0000000..9e07c1f --- /dev/null +++ b/src/main/java/com/ifish/jpush/device/AliasDeviceListResult.java @@ -0,0 +1,14 @@ +package com.ifish.jpush.device; + +import java.util.ArrayList; +import java.util.List; + +import com.google.gson.annotations.Expose; +import com.ifish.jpush.common.resp.BaseResult; + +public class AliasDeviceListResult extends BaseResult { + + @Expose public List registration_ids = new ArrayList(); + +} + diff --git a/src/main/java/com/ifish/jpush/device/DeviceClient.java b/src/main/java/com/ifish/jpush/device/DeviceClient.java new file mode 100644 index 0000000..50a3937 --- /dev/null +++ b/src/main/java/com/ifish/jpush/device/DeviceClient.java @@ -0,0 +1,232 @@ +package com.ifish.jpush.device; + +import java.lang.reflect.Type; +import java.util.Map; +import java.util.Set; + +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import com.google.gson.reflect.TypeToken; +import com.ifish.jpush.common.ClientConfig; +import com.ifish.jpush.common.ServiceHelper; +import com.ifish.jpush.common.connection.HttpProxy; +import com.ifish.jpush.common.connection.IHttpClient; +import com.ifish.jpush.common.connection.NativeHttpClient; +import com.ifish.jpush.common.resp.APIConnectionException; +import com.ifish.jpush.common.resp.APIRequestException; +import com.ifish.jpush.common.resp.BaseResult; +import com.ifish.jpush.common.resp.BooleanResult; +import com.ifish.jpush.common.resp.DefaultResult; +import com.ifish.jpush.common.resp.ResponseWrapper; +import com.ifish.jpush.utils.Preconditions; + +public class DeviceClient { + + private final NativeHttpClient _httpClient; + private String hostName; + private String devicesPath; + private String tagsPath; + private String aliasesPath; + + public DeviceClient(String masterSecret, String appKey) { + this(masterSecret, appKey, IHttpClient.DEFAULT_MAX_RETRY_TIMES); + } + + public DeviceClient(String masterSecret, String appKey, int maxRetryTimes) { + this(masterSecret, appKey, maxRetryTimes, null); + } + + public DeviceClient(String masterSecret, String appKey, int maxRetryTimes, HttpProxy proxy) { + this(masterSecret, appKey, maxRetryTimes, proxy, ClientConfig.getInstance()); + } + + /** + * + * @param masterSecret API access secret of the appKey. + * @param appKey The KEY of one application on JPush. + * @param maxRetryTimes Max retry times + * @param proxy The proxy, if there is no proxy, should be null. + * @param conf The client configuration. Can use ClientConfig.getInstance() as default. + */ + public DeviceClient(String masterSecret, String appKey, int maxRetryTimes, HttpProxy proxy, ClientConfig conf) { + ServiceHelper.checkBasic(appKey, masterSecret); + + hostName = (String) conf.get(ClientConfig.DEVICE_HOST_NAME); + devicesPath = (String) conf.get(ClientConfig.DEVICES_PATH); + tagsPath = (String) conf.get(ClientConfig.TAGS_PATH); + aliasesPath = (String) conf.get(ClientConfig.ALIASES_PATH); + + String authCode = ServiceHelper.getBasicAuthorization(appKey, masterSecret); + _httpClient = new NativeHttpClient(authCode, maxRetryTimes, proxy); + } + + // -------------- device + + public TagAliasResult getDeviceTagAlias(String registrationId) throws APIConnectionException, APIRequestException { + String url = hostName + devicesPath + "/" + registrationId; + + ResponseWrapper response = _httpClient.sendGet(url); + + return BaseResult.fromResponse(response, TagAliasResult.class); + } + + public DefaultResult updateDeviceTagAlias(String registrationId, boolean clearAlias, boolean clearTag) throws APIConnectionException, APIRequestException { + Preconditions.checkArgument(clearAlias || clearTag, "It is not meaningful to do nothing."); + + String url = hostName + devicesPath + "/" + registrationId; + + JsonObject top = new JsonObject(); + if (clearAlias) { + top.addProperty("alias", ""); + } + if (clearTag) { + top.addProperty("tags", ""); + } + + ResponseWrapper response = _httpClient.sendPost(url, top.toString()); + + return DefaultResult.fromResponse(response); + } + + public DefaultResult updateDeviceTagAlias(String registrationId, String alias, + Set tagsToAdd, Set tagsToRemove) throws APIConnectionException, APIRequestException { + String url = hostName + devicesPath + "/" + registrationId; + + JsonObject top = new JsonObject(); + if (null != alias) { + top.addProperty("alias", alias); + } + + JsonObject tagObject = new JsonObject(); + JsonArray tagsAdd = ServiceHelper.fromSet(tagsToAdd); + if (tagsAdd.size() > 0) { + tagObject.add("add", tagsAdd); + } + + JsonArray tagsRemove = ServiceHelper.fromSet(tagsToRemove); + if (tagsRemove.size() > 0) { + tagObject.add("remove", tagsRemove); + } + + if (tagObject.entrySet().size() > 0) { + top.add("tags", tagObject); + } + + ResponseWrapper response = _httpClient.sendPost(url, top.toString()); + + return DefaultResult.fromResponse(response); + } + + // ------------- tags + + public TagListResult getTagList() throws APIConnectionException, APIRequestException { + String url = hostName + tagsPath + "/"; + + ResponseWrapper response = _httpClient.sendGet(url); + + return TagListResult.fromResponse(response, TagListResult.class); + } + + public BooleanResult isDeviceInTag(String theTag, String registrationID) throws APIConnectionException, APIRequestException { + String url = hostName + tagsPath + "/" + theTag + "/registration_ids/" + registrationID; + ResponseWrapper response = _httpClient.sendGet(url); + + return BaseResult.fromResponse(response, BooleanResult.class); + } + + public DefaultResult addRemoveDevicesFromTag(String theTag, Set toAddUsers, Set toRemoveUsers) throws APIConnectionException, APIRequestException { + String url = hostName + tagsPath + "/" + theTag; + + JsonObject top = new JsonObject(); + JsonObject registrationIds = new JsonObject(); + + if (null != toAddUsers && toAddUsers.size() > 0) { + JsonArray array = new JsonArray(); + for (String user : toAddUsers) { + array.add(new JsonPrimitive(user)); + } + registrationIds.add("add", array); + } + if (null != toRemoveUsers && toRemoveUsers.size() > 0) { + JsonArray array = new JsonArray(); + for (String user : toRemoveUsers) { + array.add(new JsonPrimitive(user)); + } + registrationIds.add("remove", array); + } + + top.add("registration_ids", registrationIds); + + ResponseWrapper response = _httpClient.sendPost(url, top.toString()); + + return DefaultResult.fromResponse(response); + } + + public DefaultResult deleteTag(String theTag, String platform) throws APIConnectionException, APIRequestException { + String url = hostName + tagsPath + "/" + theTag; + if (null != platform) { + url += "?platform=" + platform; + } + + ResponseWrapper response = _httpClient.sendDelete(url); + + return DefaultResult.fromResponse(response); + } + + + // ------------- alias + + public AliasDeviceListResult getAliasDeviceList(String alias, String platform) throws APIConnectionException, APIRequestException { + String url = hostName + aliasesPath + "/" + alias; + if (null != platform) { + url += "?platform=" + platform; + } + + ResponseWrapper response = _httpClient.sendGet(url); + + return BaseResult.fromResponse(response, AliasDeviceListResult.class); + } + + public DefaultResult deleteAlias(String alias, String platform) throws APIConnectionException, APIRequestException { + String url = hostName + aliasesPath + "/" + alias; + if (null != platform) { + url += "?platform=" + platform; + } + + ResponseWrapper response = _httpClient.sendDelete(url); + + return DefaultResult.fromResponse(response); + } + + // -------------- devices status + + public Map getUserOnlineStatus(String... registrationIds) + throws APIConnectionException, APIRequestException + { + Preconditions.checkArgument((null != registrationIds ), + "The registration id list should not be null."); + Preconditions.checkArgument(registrationIds!=null && registrationIds.length > 0 && registrationIds.length <= 1000, + "The length of registration id list should between 1 and 1000."); + + String url = hostName + devicesPath + "/status"; + JsonObject json = new JsonObject(); + JsonArray array = new JsonArray(); + if(registrationIds!=null){ + for(int i = 0; i < registrationIds.length; i++) { + array.add(new JsonPrimitive(registrationIds[i])); + } + } + json.add("registration_ids", array); + Type type = new TypeToken>(){}.getType(); + ResponseWrapper response = _httpClient.sendPost(url, json.toString()); + Map map = new Gson().fromJson(response.responseContent, type); + return map; + } + +} + + + + diff --git a/src/main/java/com/ifish/jpush/device/OnlineStatus.java b/src/main/java/com/ifish/jpush/device/OnlineStatus.java new file mode 100644 index 0000000..8b2376a --- /dev/null +++ b/src/main/java/com/ifish/jpush/device/OnlineStatus.java @@ -0,0 +1,31 @@ +package com.ifish.jpush.device; + +public class OnlineStatus { + + Boolean online; + String last_online_time; + + public Boolean getOnline() { + return online; + } + + public void setOnline(Boolean online) { + this.online = online; + } + + public String getLast_online_time() { + return last_online_time; + } + + public void setLast_online_time(String last_online_time) { + this.last_online_time = last_online_time; + } + + @Override + public String toString() { + if(null == last_online_time) { + return "status: " + online; + } + return "status: " + online + " , last_online_time: " + last_online_time; + } +} diff --git a/src/main/java/com/ifish/jpush/device/TagAliasResult.java b/src/main/java/com/ifish/jpush/device/TagAliasResult.java new file mode 100644 index 0000000..63276a1 --- /dev/null +++ b/src/main/java/com/ifish/jpush/device/TagAliasResult.java @@ -0,0 +1,14 @@ +package com.ifish.jpush.device; + +import java.util.List; + +import com.google.gson.annotations.Expose; +import com.ifish.jpush.common.resp.BaseResult; + +public class TagAliasResult extends BaseResult { + + @Expose public List tags; + @Expose public String alias; + +} + diff --git a/src/main/java/com/ifish/jpush/device/TagListResult.java b/src/main/java/com/ifish/jpush/device/TagListResult.java new file mode 100644 index 0000000..5c38a9e --- /dev/null +++ b/src/main/java/com/ifish/jpush/device/TagListResult.java @@ -0,0 +1,14 @@ +package com.ifish.jpush.device; + +import java.util.ArrayList; +import java.util.List; + +import com.google.gson.annotations.Expose; +import com.ifish.jpush.common.resp.BaseResult; + +public class TagListResult extends BaseResult { + + @Expose public List tags = new ArrayList(); + +} + diff --git a/src/main/java/com/ifish/jpush/examples/DevcieExample.java b/src/main/java/com/ifish/jpush/examples/DevcieExample.java new file mode 100644 index 0000000..f1d1602 --- /dev/null +++ b/src/main/java/com/ifish/jpush/examples/DevcieExample.java @@ -0,0 +1,68 @@ +package com.ifish.jpush.examples; + +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.ifish.jpush.JPushClient; +import com.ifish.jpush.common.resp.APIConnectionException; +import com.ifish.jpush.common.resp.APIRequestException; +import com.ifish.jpush.device.OnlineStatus; +import com.ifish.jpush.device.TagAliasResult; + +public class DevcieExample { + protected static final Logger LOG = LoggerFactory.getLogger(DevcieExample.class); + + private static final String appKey = "dd1066407b044738b6479275"; + private static final String masterSecret = "6b135be0037a5c1e693c3dfa"; + private static final String TAG1 = "tag1"; + private static final String ALIAS1 = "alias1"; + private static final String ALIAS2 = "alias2"; + private static final String REGISTRATION_ID1 = "0900e8d85ef"; + private static final String REGISTRATION_ID2 = "0a04ad7d8b4"; + + private static JPushClient jpushClient = new JPushClient(masterSecret, appKey); + + public static void main(String[] args) { +// testGetDeviceTagAlias(); + testGetUserOnlineStatus(); + } + + public static void testGetDeviceTagAlias() { + try { + TagAliasResult result = jpushClient.getDeviceTagAlias(REGISTRATION_ID1); + + LOG.info(result.alias); + LOG.info(result.tags.toString()); + + } catch (APIConnectionException e) { + LOG.error("Connection error. Should retry later. ", e); + + } catch (APIRequestException e) { + LOG.error("Error response from JPush server. Should review and fix it. ", e); + LOG.info("HTTP Status: " + e.getStatus()); + LOG.info("Error Code: " + e.getErrorCode()); + LOG.info("Error Message: " + e.getErrorMessage()); + } + } + + public static void testGetUserOnlineStatus() { + try { + Map result = jpushClient.getUserOnlineStatus(REGISTRATION_ID1, REGISTRATION_ID2); + + LOG.info(result.get(REGISTRATION_ID1).toString()); + LOG.info(result.get(REGISTRATION_ID2).toString()); + } catch (APIConnectionException e) { + LOG.error("Connection error. Should retry later. ", e); + } catch (APIRequestException e) { + LOG.error("Error response from JPush server. Should review and fix it. ", e); + LOG.info("HTTP Status: " + e.getStatus()); + LOG.info("Error Code: " + e.getErrorCode()); + LOG.info("Error Message: " + e.getErrorMessage()); + } + } + +} + + diff --git a/src/main/java/com/ifish/jpush/examples/PushExample.java b/src/main/java/com/ifish/jpush/examples/PushExample.java new file mode 100644 index 0000000..70de5e6 --- /dev/null +++ b/src/main/java/com/ifish/jpush/examples/PushExample.java @@ -0,0 +1,204 @@ +package com.ifish.jpush.examples; + +import java.util.HashMap; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.JsonObject; +import com.ifish.jpush.JPushClient; +import com.ifish.jpush.common.ClientConfig; +import com.ifish.jpush.common.resp.APIConnectionException; +import com.ifish.jpush.common.resp.APIRequestException; +import com.ifish.jpush.push.PushResult; +import com.ifish.jpush.push.model.Message; +import com.ifish.jpush.push.model.Options; +import com.ifish.jpush.push.model.Platform; +import com.ifish.jpush.push.model.PushPayload; +import com.ifish.jpush.push.model.audience.Audience; +import com.ifish.jpush.push.model.audience.AudienceTarget; +import com.ifish.jpush.push.model.notification.AndroidNotification; +import com.ifish.jpush.push.model.notification.IosNotification; +import com.ifish.jpush.push.model.notification.Notification; + +public class PushExample { + protected static final Logger LOG = LoggerFactory.getLogger(PushExample.class); + + // demo App defined in resources/jpush-api.conf + private static final String appKey ="d970d5e193cb2a0bbe41653c"; + private static final String masterSecret = "60162c8cf195ce9f4dc76629"; + + public static final String TITLE = "Test from API example"; + public static final String ALERT = "Test from API Example - alert"; + public static final String MSG_CONTENT = "Test from API Example - msgContent"; + public static final String REGISTRATION_ID = "0900e8d85ef"; + public static final String TAG = "tag_api"; + + public static void main(String[] args) { + //testSendPushWithCustomConfig(); + Map map = new HashMap(); + map.put("device_id", "1"); + map.put("device_name", "设备1"); + map.put("msg_type", "remove_device"); + testSendIosAlert("300","设备解除绑定", "你已失去对“设备1”设备的控制权", map); + //testSendAndroidNotification("40","标题401","内容40",map); + //testSendAndroidNotification("40","标题","内容"); + } + + + public static void testSendPush() { + // HttpProxy proxy = new HttpProxy("localhost", 3128); + // Can use this https proxy: https://github.com/Exa-Networks/exaproxy + JPushClient jpushClient = new JPushClient(masterSecret, appKey, 3); + + // For push, all you need do is to build PushPayload object. + PushPayload payload = buildPushObject_all_all_alert(); + + try { + PushResult result = jpushClient.sendPush(payload); + LOG.info("Got result - " + result); + + } catch (APIConnectionException e) { + LOG.error("Connection error. Should retry later. ", e); + + } catch (APIRequestException e) { + LOG.error("Error response from JPush server. Should review and fix it. ", e); + LOG.info("HTTP Status: " + e.getStatus()); + LOG.info("Error Code: " + e.getErrorCode()); + LOG.info("Error Message: " + e.getErrorMessage()); + LOG.info("Msg ID: " + e.getMsgId()); + } + } + + public static PushPayload buildPushObject_all_all_alert() { + return PushPayload.alertAll(ALERT); + } + + public static PushPayload buildPushObject_all_alias_alert() { + return PushPayload.newBuilder() + .setPlatform(Platform.all()) + .setAudience(Audience.alias("alias1")) + .setNotification(Notification.alert(ALERT)) + .build(); + } + + public static PushPayload buildPushObject_android_tag_alertWithTitle() { + return PushPayload.newBuilder() + .setPlatform(Platform.android()) + .setAudience(Audience.tag("tag1")) + .setNotification(Notification.android(ALERT, TITLE, null)) + .build(); + } + + public static PushPayload buildPushObject_android_and_ios() { + return PushPayload.newBuilder() + .setPlatform(Platform.android_ios()) + .setAudience(Audience.tag("tag1")) + .setNotification(Notification.newBuilder() + .setAlert("alert content") + .addPlatformNotification(AndroidNotification.newBuilder() + .setTitle("Android Title").build()) + .addPlatformNotification(IosNotification.newBuilder() + .incrBadge(1) + .addExtra("extra_key", "extra_value").build()) + .build()) + .build(); + } + + public static PushPayload buildPushObject_ios_tagAnd_alertWithExtrasAndMessage() { + return PushPayload.newBuilder() + .setPlatform(Platform.ios()) + .setAudience(Audience.tag_and("tag1", "tag_all")) + .setNotification(Notification.newBuilder() + .addPlatformNotification(IosNotification.newBuilder() + .setAlert(ALERT) + .setBadge(5) + .setSound("happy") + .addExtra("from", "JPush") + .build()) + .build()) + .setMessage(Message.content(MSG_CONTENT)) + .setOptions(Options.newBuilder() + .setApnsProduction(true) + .build()) + .build(); + } + + public static PushPayload buildPushObject_ios_audienceMore_messageWithExtras() { + return PushPayload.newBuilder() + .setPlatform(Platform.android_ios()) + .setAudience(Audience.newBuilder() + .addAudienceTarget(AudienceTarget.tag("tag1", "tag2")) + .addAudienceTarget(AudienceTarget.alias("alias1", "alias2")) + .build()) + .setMessage(Message.newBuilder() + .setMsgContent(MSG_CONTENT) + .addExtra("from", "JPush") + .build()) + .build(); + } + + public static void testSendPushWithCustomConfig() { + ClientConfig config = ClientConfig.getInstance(); + // Setup the custom hostname + config.setPushHostName("https://api.jpush.cn"); + + JPushClient jpushClient = new JPushClient(masterSecret, appKey, 3, null, config); + + // For push, all you need do is to build PushPayload object. + PushPayload payload = buildPushObject_all_all_alert(); + + try { + PushResult result = jpushClient.sendPush(payload); + LOG.info("Got result - " + result); + + } catch (APIConnectionException e) { + LOG.error("Connection error. Should retry later. ", e); + + } catch (APIRequestException e) { + LOG.error("Error response from JPush server. Should review and fix it. ", e); + LOG.info("HTTP Status: " + e.getStatus()); + LOG.info("Error Code: " + e.getErrorCode()); + LOG.info("Error Message: " + e.getErrorMessage()); + LOG.info("Msg ID: " + e.getMsgId()); + } + } + + public static void testSendIosAlert(String alias,String title,String body,Map extras) { + JPushClient jpushClient = new JPushClient(masterSecret, appKey, true ,86400); + try { + JsonObject json = new JsonObject(); + json.addProperty("title", title); + json.addProperty("body", body); + PushResult result = jpushClient.sendIosNotificationWithAlias(json, extras, alias); + System.out.println("Got result - " + result); + } catch (APIConnectionException e) { + LOG.error("Connection error. Should retry later. ", e); + } catch (APIRequestException e) { + LOG.error("Error response from JPush server. Should review and fix it. "+e); + LOG.error("HTTP Status: " + e.getStatus()); + LOG.error("Error Code: " + e.getErrorCode()); + System.out.println(e.getErrorCode()); + LOG.error("Error Message: " + e.getErrorMessage()); + } + } + + public static void testSendAndroidNotification(String alias,String title,String alert,Map map) { + JPushClient jpushClient = new JPushClient(masterSecret, appKey , true ,86400); + try { + PushResult result = jpushClient.sendAndroidNotificationWithAlias(title ,alert, map, alias); + System.out.println("Got result - " + result); + } catch (APIConnectionException e) { + LOG.error("Connection error. Should retry later. ", e); + } catch (APIRequestException e) { + LOG.error("Error response from JPush server. Should review and fix it. "+e); + LOG.error("HTTP Status: " + e.getStatus()); + LOG.error("Error Code: " + e.getErrorCode()); + System.out.println(e.getMessage()); + LOG.error("Error Message: " + e.getErrorMessage()); + } + } + +} + diff --git a/src/main/java/com/ifish/jpush/examples/ReportsExample.java b/src/main/java/com/ifish/jpush/examples/ReportsExample.java new file mode 100644 index 0000000..cc395ed --- /dev/null +++ b/src/main/java/com/ifish/jpush/examples/ReportsExample.java @@ -0,0 +1,80 @@ +package com.ifish.jpush.examples; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.ifish.jpush.JPushClient; +import com.ifish.jpush.common.TimeUnit; +import com.ifish.jpush.common.resp.APIConnectionException; +import com.ifish.jpush.common.resp.APIRequestException; +import com.ifish.jpush.report.MessagesResult; +import com.ifish.jpush.report.ReceivedsResult; +import com.ifish.jpush.report.UsersResult; + +public class ReportsExample { + protected static final Logger LOG = LoggerFactory.getLogger(ReportsExample.class); + + // demo App defined in resources/jpush-api.conf + private static final String appKey = "dd1066407b044738b6479275"; + private static final String masterSecret = "2b38ce69b1de2a7fa95706ea"; + + public static void main(String[] args) { + testGetReport(); + testGetMessages(); + testGetUsers(); + } + + + public static void testGetReport() { + JPushClient jpushClient = new JPushClient(masterSecret, appKey); + try { + ReceivedsResult result = jpushClient.getReportReceiveds("1942377665"); + LOG.debug("Got result - " + result); + + } catch (APIConnectionException e) { + LOG.error("Connection error. Should retry later. ", e); + + } catch (APIRequestException e) { + LOG.error("Error response from JPush server. Should review and fix it. ", e); + LOG.info("HTTP Status: " + e.getStatus()); + LOG.info("Error Code: " + e.getErrorCode()); + LOG.info("Error Message: " + e.getErrorMessage()); + } + } + + public static void testGetUsers() { + JPushClient jpushClient = new JPushClient(masterSecret, appKey); + try { + UsersResult result = jpushClient.getReportUsers(TimeUnit.DAY, "2014-06-10", 3); + LOG.debug("Got result - " + result); + + } catch (APIConnectionException e) { + LOG.error("Connection error. Should retry later. ", e); + + } catch (APIRequestException e) { + LOG.error("Error response from JPush server. Should review and fix it. ", e); + LOG.info("HTTP Status: " + e.getStatus()); + LOG.info("Error Code: " + e.getErrorCode()); + LOG.info("Error Message: " + e.getErrorMessage()); + } + } + + public static void testGetMessages() { + JPushClient jpushClient = new JPushClient(masterSecret, appKey); + try { + MessagesResult result = jpushClient.getReportMessages("269978303"); + LOG.debug("Got result - " + result); + + } catch (APIConnectionException e) { + LOG.error("Connection error. Should retry later. ", e); + + } catch (APIRequestException e) { + LOG.error("Error response from JPush server. Should review and fix it. ", e); + LOG.info("HTTP Status: " + e.getStatus()); + LOG.info("Error Code: " + e.getErrorCode()); + LOG.info("Error Message: " + e.getErrorMessage()); + } + } + +} + diff --git a/src/main/java/com/ifish/jpush/examples/ScheduleExample.java b/src/main/java/com/ifish/jpush/examples/ScheduleExample.java new file mode 100644 index 0000000..279d394 --- /dev/null +++ b/src/main/java/com/ifish/jpush/examples/ScheduleExample.java @@ -0,0 +1,191 @@ +package com.ifish.jpush.examples; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.ifish.jpush.JPushClient; +import com.ifish.jpush.common.TimeUnit; +import com.ifish.jpush.common.Week; +import com.ifish.jpush.common.resp.APIConnectionException; +import com.ifish.jpush.common.resp.APIRequestException; +import com.ifish.jpush.push.model.PushPayload; +import com.ifish.jpush.schedule.ScheduleListResult; +import com.ifish.jpush.schedule.ScheduleResult; +import com.ifish.jpush.schedule.model.SchedulePayload; +import com.ifish.jpush.schedule.model.TriggerPayload; + +public class ScheduleExample { + + protected static final Logger LOG = LoggerFactory.getLogger(ScheduleExample.class); + + private static final String appKey ="e5c0d34f58732cf09b2d4d74"; + private static final String masterSecret = "4cdda6d3c8b029941dbc5cb3"; + + public static void main(String[] args) { + +// testDeleteSchedule(); + testGetScheduleList(); +// testUpdateSchedule(); + testGetSchedule(); + } + + public static void testCreateSingleSchedule() { + JPushClient jpushClient = new JPushClient(masterSecret, appKey); + String name = "test_schedule_example"; + String time = "2016-07-30 12:30:25"; + PushPayload push = PushPayload.alertAll("test schedule example."); + try { + ScheduleResult result = jpushClient.createSingleSchedule(name, time, push); + LOG.info("schedule result is " + result); + } catch (APIConnectionException e) { + LOG.error("Connection error. Should retry later. ", e); + } catch (APIRequestException e) { + LOG.error("Error response from JPush server. Should review and fix it. ", e); + LOG.info("HTTP Status: " + e.getStatus()); + LOG.info("Error Code: " + e.getErrorCode()); + LOG.info("Error Message: " + e.getErrorMessage()); + } + } + + public static void testCreateDailySchedule() { + JPushClient jPushClient = new JPushClient(masterSecret, appKey); + String name = "test_daily_schedule"; + String start = "2015-08-06 12:16:13"; + String end = "2115-08-06 12:16:13"; + String time = "14:00:00"; + PushPayload push = PushPayload.alertAll("test daily example."); + try { + ScheduleResult result = jPushClient.createDailySchedule(name, start, end, time, push); + LOG.info("schedule result is " + result); + } catch (APIConnectionException e) { + LOG.error("Connection error. Should retry later. ", e); + } catch (APIRequestException e) { + LOG.error("Error response from JPush server. Should review and fix it. ", e); + LOG.info("HTTP Status: " + e.getStatus()); + LOG.info("Error Code: " + e.getErrorCode()); + LOG.info("Error Message: " + e.getErrorMessage()); + } + } + + public static void testCreateWeeklySchedule() { + JPushClient jPushClient = new JPushClient(masterSecret, appKey); + String name = "test_weekly_schedule"; + String start = "2015-08-06 12:16:13"; + String end = "2115-08-06 12:16:13"; + String time = "14:00:00"; + Week[] days = {Week.MON, Week.FRI}; + PushPayload push = PushPayload.alertAll("test weekly example."); + try { + ScheduleResult result = jPushClient.createWeeklySchedule(name, start, end, time, days, push); + LOG.info("schedule result is " + result); + } catch (APIConnectionException e) { + LOG.error("Connection error. Should retry later. ", e); + } catch (APIRequestException e) { + LOG.error("Error response from JPush server. Should review and fix it. ", e); + LOG.info("HTTP Status: " + e.getStatus()); + LOG.info("Error Code: " + e.getErrorCode()); + LOG.info("Error Message: " + e.getErrorMessage()); + } + } + + public static void testCreateMonthlySchedule() { + JPushClient jPushClient = new JPushClient(masterSecret, appKey); + String name = "test_monthly_schedule"; + String start = "2015-08-06 12:16:13"; + String end = "2115-08-06 12:16:13"; + String time = "14:00:00"; + String[] points = {"01", "02"}; + PushPayload push = PushPayload.alertAll("test monthly example."); + try { + ScheduleResult result = jPushClient.createMonthlySchedule(name, start, end, time, points, push); + LOG.info("schedule result is " + result); + } catch (APIConnectionException e) { + LOG.error("Connection error. Should retry later.", e); + } catch (APIRequestException e) { + LOG.error("Error response from JPush server. Should review and fix it. ", e); + LOG.info("HTTP Status: " + e.getStatus()); + LOG.info("Error Code: " + e.getErrorCode()); + LOG.info("Error Message: " + e.getErrorMessage()); + } + } + + public static void testDeleteSchedule() { + String scheduleId = "95bbd066-3a88-11e5-8e62-0021f652c102"; + JPushClient jpushClient = new JPushClient(masterSecret, appKey); + + try { + jpushClient.deleteSchedule(scheduleId); + } catch (APIConnectionException e) { + LOG.error("Connection error. Should retry later. ", e); + } catch (APIRequestException e) { + LOG.error("Error response from JPush server. Should review and fix it. ", e); + LOG.info("HTTP Status: " + e.getStatus()); + LOG.info("Error Code: " + e.getErrorCode()); + LOG.info("Error Message: " + e.getErrorMessage()); + } + } + + public static void testGetScheduleList() { + int page = 1; + JPushClient jpushClient = new JPushClient(masterSecret, appKey); + + try { + ScheduleListResult list = jpushClient.getScheduleList(page); + LOG.info("total " + list.getTotal_count()); + for(ScheduleResult s : list.getSchedules()) { + LOG.info(s.toString()); + } + } catch (APIConnectionException e) { + LOG.error("Connection error. Should retry later. ", e); + } catch (APIRequestException e) { + LOG.error("Error response from JPush server. Should review and fix it. ", e); + LOG.info("HTTP Status: " + e.getStatus()); + LOG.info("Error Code: " + e.getErrorCode()); + LOG.info("Error Message: " + e.getErrorMessage()); + } + } + + public static void testUpdateSchedule() { + String scheduleId = "95bbd066-3a88-11e5-8e62-0021f652c102"; + JPushClient jpushClient = new JPushClient(masterSecret, appKey); + String[] points = {Week.MON.name(), Week.FRI.name()}; + TriggerPayload trigger = TriggerPayload.newBuilder() + .setPeriodTime("2015-08-01 12:10:00", "2015-08-30 12:12:12", "15:00:00") + .setTimeFrequency(TimeUnit.WEEK, 2, points) + .buildPeriodical(); + SchedulePayload payload = SchedulePayload.newBuilder() + .setName("test_update_schedule") + .setEnabled(false) + .setTrigger(trigger) + .build(); + try { + jpushClient.updateSchedule(scheduleId, payload); + } catch (APIConnectionException e) { + LOG.error("Connection error. Should retry later. ", e); + } catch (APIRequestException e) { + LOG.error("Error response from JPush server. Should review and fix it. ", e); + LOG.info("HTTP Status: " + e.getStatus()); + LOG.info("Error Code: " + e.getErrorCode()); + LOG.info("Error Message: " + e.getErrorMessage()); + } + } + + public static void testGetSchedule() { + String scheduleId = "95bbd066-3a88-11e5-8e62-0021f652c102"; + JPushClient jpushClient = new JPushClient(masterSecret, appKey); + + try { + ScheduleResult result = jpushClient.getSchedule(scheduleId); + LOG.info("schedule " + result); + } catch (APIConnectionException e) { + LOG.error("Connection error. Should retry later. ", e); + } catch (APIRequestException e) { + LOG.error("Error response from JPush server. Should review and fix it. ", e); + LOG.info("HTTP Status: " + e.getStatus()); + LOG.info("Error Code: " + e.getErrorCode()); + LOG.info("Error Message: " + e.getErrorMessage()); + } + } + + +} diff --git a/src/main/java/com/ifish/jpush/push/PushClient.java b/src/main/java/com/ifish/jpush/push/PushClient.java new file mode 100644 index 0000000..d861403 --- /dev/null +++ b/src/main/java/com/ifish/jpush/push/PushClient.java @@ -0,0 +1,168 @@ +package com.ifish.jpush.push; + +import com.google.gson.JsonParseException; +import com.google.gson.JsonParser; +import com.ifish.jpush.common.ClientConfig; +import com.ifish.jpush.common.ServiceHelper; +import com.ifish.jpush.common.connection.HttpProxy; +import com.ifish.jpush.common.connection.IHttpClient; +import com.ifish.jpush.common.connection.NativeHttpClient; +import com.ifish.jpush.common.resp.APIConnectionException; +import com.ifish.jpush.common.resp.APIRequestException; +import com.ifish.jpush.common.resp.BaseResult; +import com.ifish.jpush.common.resp.ResponseWrapper; +import com.ifish.jpush.push.model.PushPayload; +import com.ifish.jpush.utils.Preconditions; +import com.ifish.jpush.utils.StringUtils; + + +/** + * Entrance for sending Push. + * + * For the following parameters, you can set them by instance creation. + * This action will override setting in PushPayload Optional. + * * apnsProduction If not present, the default is true. + * * timeToLive If not present, the default is 86400(s) (one day). + * + * Can be used directly. + */ +public class PushClient { + + private final NativeHttpClient _httpClient; + private String _baseUrl; + private String _pushPath; + private String _pushValidatePath; + + private JsonParser _jsonParser = new JsonParser(); + + // If not present, true by default. + private boolean _apnsProduction = true; + + // If not present, the default value is 86400(s) (one day) + private long _timeToLive = 60 * 60 * 24; + + private boolean _globalSettingEnabled = false; + + /** + * Create a Push Client. + * + * @param masterSecret API access secret of the appKey. + * @param appKey The KEY of one application on JPush. + */ + public PushClient(String masterSecret, String appKey) { + this(masterSecret, appKey, IHttpClient.DEFAULT_MAX_RETRY_TIMES); + } + + public PushClient(String masterSecret, String appKey, int maxRetryTimes) { + this(masterSecret, appKey, maxRetryTimes, null); + } + + /** + * Create a Push Client with max retry times. + * + * @param masterSecret API access secret of the appKey. + * @param appKey The KEY of one application on JPush. + * @param maxRetryTimes max retry times + */ + public PushClient(String masterSecret, String appKey, int maxRetryTimes, HttpProxy proxy) { + this(masterSecret, appKey, maxRetryTimes, proxy, ClientConfig.getInstance()); + } + + public PushClient(String masterSecret, String appKey, int maxRetryTimes, HttpProxy proxy, ClientConfig conf) { + ServiceHelper.checkBasic(appKey, masterSecret); + + this._baseUrl = (String) conf.get(ClientConfig.PUSH_HOST_NAME); + this._pushPath = (String) conf.get(ClientConfig.PUSH_PATH); + this._pushValidatePath = (String) conf.get(ClientConfig.PUSH_VALIDATE_PATH); + + String authCode = ServiceHelper.getBasicAuthorization(appKey, masterSecret); + this._httpClient = new NativeHttpClient(authCode, maxRetryTimes, proxy); + + } + + /** + * Create a Push Client with global settings. + * + * If you want different settings from default globally, this constructor is what you needed. + * + * @param masterSecret API access secret of the appKey. + * @param appKey The KEY of one application on JPush. + * @param apnsProduction Global APNs environment setting. It will override PushPayload Options. + * @param timeToLive Global time_to_live setting. It will override PushPayload Options. + */ + public PushClient(String masterSecret, String appKey, boolean apnsProduction, long timeToLive) { + this(masterSecret, appKey); + + this._apnsProduction = apnsProduction; + this._timeToLive = timeToLive; + this._globalSettingEnabled = true; + } + + public void setDefaults(boolean apnsProduction, long timeToLive) { + this._apnsProduction = apnsProduction; + this._timeToLive = timeToLive; + this._globalSettingEnabled = true; + } + + public void setBaseUrl(String baseUrl) { + this._baseUrl = baseUrl; + } + + public PushResult sendPush(PushPayload pushPayload) throws APIConnectionException, APIRequestException { + Preconditions.checkArgument(! (null == pushPayload), "pushPayload should not be null"); + + if (_globalSettingEnabled) { + pushPayload.resetOptionsTimeToLive(_timeToLive); + pushPayload.resetOptionsApnsProduction(_apnsProduction); + } + + ResponseWrapper response = _httpClient.sendPost(_baseUrl + _pushPath, pushPayload.toString()); + + return BaseResult.fromResponse(response, PushResult.class); + } + + public PushResult sendPushValidate(PushPayload pushPayload) throws APIConnectionException, APIRequestException { + Preconditions.checkArgument(! (null == pushPayload), "pushPayload should not be null"); + + if (_globalSettingEnabled) { + pushPayload.resetOptionsTimeToLive(_timeToLive); + pushPayload.resetOptionsApnsProduction(_apnsProduction); + } + + ResponseWrapper response = _httpClient.sendPost(_baseUrl + _pushValidatePath, pushPayload.toString()); + + return BaseResult.fromResponse(response, PushResult.class); + } + + public PushResult sendPush(String payloadString) throws APIConnectionException, APIRequestException { + Preconditions.checkArgument(StringUtils.isNotEmpty(payloadString), "pushPayload should not be empty"); + + try { + _jsonParser.parse(payloadString); + } catch (JsonParseException e) { + Preconditions.checkArgument(false, "payloadString should be a valid JSON string."); + } + + ResponseWrapper response = _httpClient.sendPost(_baseUrl + _pushPath, payloadString); + + return BaseResult.fromResponse(response, PushResult.class); + } + + public PushResult sendPushValidate(String payloadString) throws APIConnectionException, APIRequestException { + Preconditions.checkArgument(StringUtils.isNotEmpty(payloadString), "pushPayload should not be empty"); + + try { + _jsonParser.parse(payloadString); + } catch (JsonParseException e) { + Preconditions.checkArgument(false, "payloadString should be a valid JSON string."); + } + + ResponseWrapper response = _httpClient.sendPost(_baseUrl + _pushValidatePath, payloadString); + + return BaseResult.fromResponse(response, PushResult.class); + } + + +} + + diff --git a/src/main/java/com/ifish/jpush/push/PushResult.java b/src/main/java/com/ifish/jpush/push/PushResult.java new file mode 100644 index 0000000..e78d401 --- /dev/null +++ b/src/main/java/com/ifish/jpush/push/PushResult.java @@ -0,0 +1,12 @@ +package com.ifish.jpush.push; + +import com.google.gson.annotations.Expose; +import com.ifish.jpush.common.resp.BaseResult; + +public class PushResult extends BaseResult { + + @Expose public long msg_id; + @Expose public int sendno; + +} + diff --git a/src/main/java/com/ifish/jpush/push/model/Message.java b/src/main/java/com/ifish/jpush/push/model/Message.java new file mode 100644 index 0000000..05335b9 --- /dev/null +++ b/src/main/java/com/ifish/jpush/push/model/Message.java @@ -0,0 +1,153 @@ +package com.ifish.jpush.push.model; + +import java.util.HashMap; +import java.util.Map; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import com.ifish.jpush.utils.Preconditions; + +public class Message implements PushModel { + private static final String TITLE = "title"; + private static final String MSG_CONTENT = "msg_content"; + private static final String CONTENT_TYPE = "content_type"; + private static final String EXTRAS = "extras"; + + private final String title; + private final String msgContent; + private final String contentType; + private final Map extras; + private final Map numberExtras; + private final Map booleanExtras; + + private Message(String title, String msgContent, String contentType, + Map extras, + Map numberExtras, + Map booleanExtras) { + this.title = title; + this.msgContent = msgContent; + this.contentType = contentType; + this.extras = extras; + this.numberExtras = numberExtras; + this.booleanExtras = booleanExtras; + } + + public static Builder newBuilder() { + return new Builder(); + } + + public static Message content(String msgContent) { + return new Builder().setMsgContent(msgContent).build(); + } + + @Override + public JsonElement toJSON() { + JsonObject json = new JsonObject(); + if (null != title) { + json.add(TITLE, new JsonPrimitive(title)); + } + if (null != msgContent) { + json.add(MSG_CONTENT, new JsonPrimitive(msgContent)); + } + if (null != contentType) { + json.add(CONTENT_TYPE, new JsonPrimitive(contentType)); + } + + JsonObject extrasObject = null; + if (null != extras || null != numberExtras || null != booleanExtras) { + extrasObject = new JsonObject(); + } + + if (null != extras) { + for (String key : extras.keySet()) { + extrasObject.add(key, new JsonPrimitive(extras.get(key))); + } + } + if (null != numberExtras) { + for (String key : numberExtras.keySet()) { + extrasObject.add(key, new JsonPrimitive(numberExtras.get(key))); + } + } + if (null != booleanExtras) { + for (String key : booleanExtras.keySet()) { + extrasObject.add(key, new JsonPrimitive(booleanExtras.get(key))); + } + } + + if (null != extras || null != numberExtras || null != booleanExtras) { + json.add(EXTRAS, extrasObject); + } + + return json; + } + + public static class Builder { + private String title; + private String msgContent; + private String contentType; + private Map extrasBuilder; + private Map numberExtrasBuilder; + private Map booleanExtrasBuilder; + + public Builder setTitle(String title) { + this.title = title; + return this; + } + + public Builder setMsgContent(String msgContent) { + this.msgContent = msgContent; + return this; + } + + public Builder setContentType(String contentType) { + this.contentType = contentType; + return this; + } + + public Builder addExtra(String key, String value) { + Preconditions.checkArgument(! (null == key || null == value), "Key/Value should not be null."); + if (null == extrasBuilder) { + extrasBuilder = new HashMap(); + } + extrasBuilder.put(key, value); + return this; + } + + public Builder addExtras(Map extras) { + Preconditions.checkArgument(! (null == extras), "extras should not be null."); + if (null == extrasBuilder) { + extrasBuilder = new HashMap(); + } + for (String key : extras.keySet()) { + extrasBuilder.put(key, extras.get(key)); + } + return this; + } + + public Builder addExtra(String key, Number value) { + Preconditions.checkArgument(! (null == key || null == value), "Key/Value should not be null."); + if (null == numberExtrasBuilder) { + numberExtrasBuilder = new HashMap(); + } + numberExtrasBuilder.put(key, value); + return this; + } + + public Builder addExtra(String key, Boolean value) { + Preconditions.checkArgument(! (null == key || null == value), "Key/Value should not be null."); + if (null == booleanExtrasBuilder) { + booleanExtrasBuilder = new HashMap(); + } + booleanExtrasBuilder.put(key, value); + return this; + } + + public Message build() { + Preconditions.checkArgument(! (null == msgContent), + "msgContent should be set"); + return new Message(title, msgContent, contentType, + extrasBuilder, numberExtrasBuilder, booleanExtrasBuilder); + } + } +} diff --git a/src/main/java/com/ifish/jpush/push/model/Options.java b/src/main/java/com/ifish/jpush/push/model/Options.java new file mode 100644 index 0000000..596b3f2 --- /dev/null +++ b/src/main/java/com/ifish/jpush/push/model/Options.java @@ -0,0 +1,128 @@ +package com.ifish.jpush.push.model; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import com.ifish.jpush.common.ServiceHelper; +import com.ifish.jpush.utils.Preconditions; + +public class Options implements PushModel { + private static final String SENDNO = "sendno"; + private static final String OVERRIDE_MSG_ID = "override_msg_id"; + private static final String TIME_TO_LIVE = "time_to_live"; + private static final String APNS_PRODUCTION = "apns_production"; + private static final String BIG_PUSH_DURATION = "big_push_duration"; + + private static final long NONE_TIME_TO_LIVE = -1; + + private final int sendno; + private final long overrideMsgId; + private long timeToLive; + private boolean apnsProduction; + private int bigPushDuration; // minutes + + private Options(int sendno, long overrideMsgId, long timeToLive, boolean apnsProduction, + int bigPushDuration) { + this.sendno = sendno; + this.overrideMsgId = overrideMsgId; + this.timeToLive = timeToLive; + this.apnsProduction = apnsProduction; + this.bigPushDuration = bigPushDuration; + } + + public static Builder newBuilder() { + return new Builder(); + } + + public static Options sendno() { + return newBuilder().setSendno(ServiceHelper.generateSendno()).build(); + } + + public static Options sendno(int sendno) { + return newBuilder().setSendno(sendno).build(); + } + + public void setApnsProduction(boolean apnsProduction) { + this.apnsProduction = apnsProduction; + } + + public void setTimeToLive(long timeToLive) { + this.timeToLive = timeToLive; + } + + public void setBigPushDuration(int bigPushDuration) { + this.bigPushDuration = bigPushDuration; + } + + public int getSendno() { + return this.sendno; + } + + @Override + public JsonElement toJSON() { + JsonObject json = new JsonObject(); + if (sendno > 0) { + json.add(SENDNO, new JsonPrimitive(sendno)); + } + if (overrideMsgId > 0) { + json.add(OVERRIDE_MSG_ID, new JsonPrimitive(overrideMsgId)); + } + if (timeToLive >= 0) { + json.add(TIME_TO_LIVE, new JsonPrimitive(timeToLive)); + } + + json.add(APNS_PRODUCTION, new JsonPrimitive(apnsProduction)); + + if (bigPushDuration > 0) { + json.add(BIG_PUSH_DURATION, new JsonPrimitive(bigPushDuration)); + } + + return json; + } + + public static class Builder { + private int sendno = 0; + private long overrideMsgId = 0; + private long timeToLive = NONE_TIME_TO_LIVE; + private boolean apnsProduction = false; + private int bigPushDuration = 0; + + public Builder setSendno(int sendno) { + this.sendno = sendno; + return this; + } + + public Builder setOverrideMsgId(long overrideMsgId) { + this.overrideMsgId = overrideMsgId; + return this; + } + + public Builder setTimeToLive(long timeToLive) { + this.timeToLive = timeToLive; + return this; + } + + public Builder setApnsProduction(boolean apnsProduction) { + this.apnsProduction = apnsProduction; + return this; + } + + public Builder setBigPushDuration(int bigPushDuration) { + this.bigPushDuration = bigPushDuration; + return this; + } + + public Options build() { + Preconditions.checkArgument(sendno >= 0, "sendno should be greater than 0."); + Preconditions.checkArgument(overrideMsgId >= 0, "override_msg_id should be greater than 0."); + Preconditions.checkArgument(timeToLive >= NONE_TIME_TO_LIVE, "time_to_live should be greater than 0."); + Preconditions.checkArgument(bigPushDuration >= 0, "bigPushDuration should be greater than 0."); + if (sendno <= 0) { + sendno = ServiceHelper.generateSendno(); + } + + return new Options(sendno, overrideMsgId, timeToLive, apnsProduction, bigPushDuration); + } + } + +} diff --git a/src/main/java/com/ifish/jpush/push/model/Platform.java b/src/main/java/com/ifish/jpush/push/model/Platform.java new file mode 100644 index 0000000..8fc0b0e --- /dev/null +++ b/src/main/java/com/ifish/jpush/push/model/Platform.java @@ -0,0 +1,108 @@ +package com.ifish.jpush.push.model; + +import java.util.HashSet; +import java.util.Set; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonPrimitive; +import com.ifish.jpush.common.DeviceType; +import com.ifish.jpush.utils.Preconditions; + +public class Platform implements PushModel { + private static final String ALL = "all"; + + private final boolean all; + private final Set deviceTypes; + + private Platform(boolean all, Set deviceTypes) { + this.all = all; + this.deviceTypes = deviceTypes; + } + + public static Builder newBuilder() { + return new Builder(); + } + + public static Platform all() { + return newBuilder().setAll(true).build(); + } + + public static Platform android() { + return newBuilder().addDeviceType(DeviceType.Android).build(); + } + + public static Platform ios() { + return newBuilder().addDeviceType(DeviceType.IOS).build(); + } + + public static Platform winphone() { + return newBuilder().addDeviceType(DeviceType.WinPhone).build(); + } + + public static Platform android_ios() { + return newBuilder() + .addDeviceType(DeviceType.Android) + .addDeviceType(DeviceType.IOS) + .build(); + } + + public static Platform android_winphone() { + return newBuilder() + .addDeviceType(DeviceType.Android) + .addDeviceType(DeviceType.WinPhone) + .build(); + } + + public static Platform ios_winphone() { + return newBuilder() + .addDeviceType(DeviceType.IOS) + .addDeviceType(DeviceType.WinPhone) + .build(); + } + + public boolean isAll() { + return all; + } + + @Override + public JsonElement toJSON() { + if (all) { + return new JsonPrimitive(ALL); + } + + JsonArray json = new JsonArray(); + for (DeviceType deviceType : deviceTypes) { + json.add(new JsonPrimitive(deviceType.value())); + } + return json; + } + + + public static class Builder { + private boolean all; + private Set deviceTypes; + + public Builder setAll(boolean all) { + this.all = all; + return this; + } + + public Builder addDeviceType(DeviceType deviceType) { + if (null == deviceTypes) { + deviceTypes = new HashSet(); + } + deviceTypes.add(deviceType); + return this; + } + + public Platform build() { + Preconditions.checkArgument(! (all && null != deviceTypes), "Since all is enabled, any platform should not be set."); + Preconditions.checkArgument(! (!all && null == deviceTypes), "No any deviceType is set."); + return new Platform(all, deviceTypes); + } + } + +} + + diff --git a/src/main/java/com/ifish/jpush/push/model/PushModel.java b/src/main/java/com/ifish/jpush/push/model/PushModel.java new file mode 100644 index 0000000..abc37db --- /dev/null +++ b/src/main/java/com/ifish/jpush/push/model/PushModel.java @@ -0,0 +1,11 @@ +package com.ifish.jpush.push.model; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; + +public interface PushModel { + + public static Gson gson = new Gson(); + public JsonElement toJSON(); + +} diff --git a/src/main/java/com/ifish/jpush/push/model/PushPayload.java b/src/main/java/com/ifish/jpush/push/model/PushPayload.java new file mode 100644 index 0000000..31b8b29 --- /dev/null +++ b/src/main/java/com/ifish/jpush/push/model/PushPayload.java @@ -0,0 +1,219 @@ +package com.ifish.jpush.push.model; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import com.ifish.jpush.push.model.audience.Audience; +import com.ifish.jpush.push.model.notification.AndroidNotification; +import com.ifish.jpush.push.model.notification.IosNotification; +import com.ifish.jpush.push.model.notification.Notification; +import com.ifish.jpush.push.model.notification.PlatformNotification; +import com.ifish.jpush.utils.Preconditions; + +/** + * The object you should build for sending a push. + * + * Basically start with newBuilder() method to build a PushPayload object. + * + * alertAll() is a shortcut for quickly build payload of alert to all platform and all audience; + * mesageAll() is a shortcut for quickly build payload of message to all platform and all audience. + * + */ +public class PushPayload implements PushModel { + private static final String PLATFORM = "platform"; + private static final String AUDIENCE = "audience"; + private static final String NOTIFICATION = "notification"; + private static final String MESSAGE = "message"; + private static final String OPTIONS = "options"; + + private static final int MAX_GLOBAL_ENTITY_LENGTH = 1200; // Definition acording to JPush Docs + private static final int MAX_IOS_PAYLOAD_LENGTH = 220; // Definition acording to JPush Docs + + private static Gson _gson = new Gson(); + + private final Platform platform; + private final Audience audience; + private final Notification notification; + private final Message message; + private Options options; + + + private PushPayload(Platform platform, Audience audience, + Notification notification, Message message, Options options) { + this.platform = platform; + this.audience = audience; + this.notification = notification; + this.message = message; + this.options = options; + } + + /** + * The entrance for building a PushPayload object. + */ + public static Builder newBuilder() { + return new Builder(); + } + + /** + * The shortcut of building a simple alert notification object to all platforms and all audiences + */ + public static PushPayload alertAll(String alert) { + return new Builder() + .setPlatform(Platform.all()) + .setAudience(Audience.all()) + .setNotification(Notification.alert(alert)).build(); + } + + /** + * The shortcut of building a simple message object to all platforms and all audiences + */ + public static PushPayload messageAll(String msgContent) { + return new Builder() + .setPlatform(Platform.all()) + .setAudience(Audience.all()) + .setMessage(Message.content(msgContent)).build(); + } + + public static PushPayload fromJSON(String payloadString) { + return _gson.fromJson(payloadString, PushPayload.class); + } + + public void resetOptionsApnsProduction(boolean apnsProduction) { + if (null == options) { + options = Options.newBuilder().setApnsProduction(apnsProduction).build(); + } else { + options.setApnsProduction(apnsProduction); + } + } + + public void resetOptionsTimeToLive(long timeToLive) { + if (null == options) { + options = Options.newBuilder().setTimeToLive(timeToLive).build(); + } else { + options.setTimeToLive(timeToLive); + } + } + + public int getSendno() { + if (null != options) { + return options.getSendno(); + } + return 0; + } + + @Override + public JsonElement toJSON() { + JsonObject json = new JsonObject(); + if (null != platform) { + json.add(PLATFORM, platform.toJSON()); + } + if (null != audience) { + json.add(AUDIENCE, audience.toJSON()); + } + if (null != notification) { + json.add(NOTIFICATION, notification.toJSON()); + } + if (null != message) { + json.add(MESSAGE, message.toJSON()); + } + if (null != options) { + json.add(OPTIONS, options.toJSON()); + } + + return json; + } + + public boolean isGlobalExceedLength() { + int messageLength = 0; + JsonObject payload = (JsonObject) this.toJSON(); + if (payload.has(MESSAGE)) { + JsonObject message = payload.getAsJsonObject(MESSAGE); + messageLength = message.toString().getBytes().length; + } + if (!payload.has(NOTIFICATION)) { + // only mesage + return messageLength > MAX_GLOBAL_ENTITY_LENGTH; + } else { + JsonObject notification = payload.getAsJsonObject(NOTIFICATION); + if (notification.has(AndroidNotification.NOTIFICATION_ANDROID)) { + JsonObject android = notification.getAsJsonObject(AndroidNotification.NOTIFICATION_ANDROID); + int androidLength = android.toString().getBytes().length; + return (androidLength + messageLength) > MAX_GLOBAL_ENTITY_LENGTH; + } + } + return false; + } + + public boolean isIosExceedLength() { + JsonObject payload = (JsonObject) this.toJSON(); + if (payload.has(NOTIFICATION)) { + JsonObject notification = payload.getAsJsonObject(NOTIFICATION); + if (notification.has(IosNotification.NOTIFICATION_IOS)) { + JsonObject ios = notification.getAsJsonObject(IosNotification.NOTIFICATION_IOS); + return ios.toString().getBytes().length > MAX_IOS_PAYLOAD_LENGTH; + } else { + if (notification.has(PlatformNotification.ALERT)) { + String alert = notification.get(PlatformNotification.ALERT).getAsString(); + JsonObject ios = new JsonObject(); + ios.add("alert", new JsonPrimitive(alert)); + return ios.toString().getBytes().length > MAX_IOS_PAYLOAD_LENGTH; + } else { + // No iOS Payload + } + } + } + return false; + } + + @Override + public String toString() { + return _gson.toJson(toJSON()); + } + + public static class Builder { + private Platform platform = null; + private Audience audience = null; + private Notification notification = null; + private Message message = null; + private Options options = null; + + public Builder setPlatform(Platform platform) { + this.platform = platform; + return this; + } + + public Builder setAudience(Audience audience) { + this.audience = audience; + return this; + } + + public Builder setNotification(Notification notification) { + this.notification = notification; + return this; + } + + public Builder setMessage(Message message) { + this.message = message; + return this; + } + + public Builder setOptions(Options options) { + this.options = options; + return this; + } + + public PushPayload build() { + Preconditions.checkArgument(! (null == audience || null == platform), "audience and platform both should be set."); + Preconditions.checkArgument(! (null == notification && null == message), "notification or message should be set at least one."); + + // if options is not set, a sendno will be generated for tracing easily + if (null == options) { + options = Options.sendno(); + } + + return new PushPayload(platform, audience, notification, message, options); + } + } +} + diff --git a/src/main/java/com/ifish/jpush/push/model/audience/Audience.java b/src/main/java/com/ifish/jpush/push/model/audience/Audience.java new file mode 100644 index 0000000..00f2066 --- /dev/null +++ b/src/main/java/com/ifish/jpush/push/model/audience/Audience.java @@ -0,0 +1,148 @@ +package com.ifish.jpush.push.model.audience; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import com.ifish.jpush.push.model.PushModel; +import com.ifish.jpush.utils.Preconditions; + +public class Audience implements PushModel { + private static final String ALL = "all"; + + private final boolean all; + private final Set targets; + + private Audience(boolean all, Set targets) { + this.all = all; + this.targets = targets; + } + + public static Builder newBuilder() { + return new Builder(); + } + + public static Audience all() { + return newBuilder().setAll(true).build(); + } + + public static Audience tag(String... tagValue) { + AudienceTarget target = AudienceTarget.newBuilder() + .setAudienceType(AudienceType.TAG) + .addAudienceTargetValues(tagValue).build(); + return newBuilder().addAudienceTarget(target).build(); + } + + public static Audience tag(Collection tagValues) { + AudienceTarget target = AudienceTarget.newBuilder() + .setAudienceType(AudienceType.TAG) + .addAudienceTargetValues(tagValues).build(); + return newBuilder().addAudienceTarget(target).build(); + } + + public static Audience tag_and(String... tagValue) { + AudienceTarget target = AudienceTarget.newBuilder() + .setAudienceType(AudienceType.TAG_AND) + .addAudienceTargetValues(tagValue).build(); + return newBuilder().addAudienceTarget(target).build(); + } + + public static Audience tag_and(Collection tagValues) { + AudienceTarget target = AudienceTarget.newBuilder() + .setAudienceType(AudienceType.TAG_AND) + .addAudienceTargetValues(tagValues).build(); + return newBuilder().addAudienceTarget(target).build(); + } + + public static Audience alias(String... alias) { + AudienceTarget target = AudienceTarget.newBuilder() + .setAudienceType(AudienceType.ALIAS) + .addAudienceTargetValues(alias).build(); + return newBuilder().addAudienceTarget(target).build(); + } + + public static Audience alias(Collection aliases) { + AudienceTarget target = AudienceTarget.newBuilder() + .setAudienceType(AudienceType.ALIAS) + .addAudienceTargetValues(aliases).build(); + return newBuilder().addAudienceTarget(target).build(); + } + + public static Audience segment(String... segment) { + AudienceTarget target = AudienceTarget.newBuilder() + .setAudienceType(AudienceType.SEGMENT) + .addAudienceTargetValues(segment).build(); + return newBuilder().addAudienceTarget(target).build(); + } + + public static Audience segment(Collection segments) { + AudienceTarget target = AudienceTarget.newBuilder() + .setAudienceType(AudienceType.SEGMENT) + .addAudienceTargetValues(segments).build(); + return newBuilder().addAudienceTarget(target).build(); + } + + public static Audience registrationId(String... registrationId) { + AudienceTarget target = AudienceTarget.newBuilder() + .setAudienceType(AudienceType.REGISTRATION_ID) + .addAudienceTargetValues(registrationId).build(); + return newBuilder().addAudienceTarget(target).build(); + } + + public static Audience registrationId(Collection registrationIds) { + AudienceTarget target = AudienceTarget.newBuilder() + .setAudienceType(AudienceType.REGISTRATION_ID) + .addAudienceTargetValues(registrationIds).build(); + return newBuilder().addAudienceTarget(target).build(); + } + + + public boolean isAll() { + return this.all; + } + + public JsonElement toJSON() { + if (all) { + return new JsonPrimitive(ALL); + } + + // if not all, there will be target be set. + JsonObject json = new JsonObject(); + if (null != targets) { + for (AudienceTarget target : targets) { + json.add(target.getAudienceTypeValue(), target.toJSON()); + } + } + return json; + } + + public static class Builder { + private boolean all = false; + private Set audienceBuilder = null; + + public Builder setAll(boolean all) { + this.all = all; + return this; + } + + public Builder addAudienceTarget(AudienceTarget target) { + if (null == audienceBuilder) { + audienceBuilder = new HashSet(); + } + audienceBuilder.add(target); + return this; + } + + public Audience build() { + Preconditions.checkArgument(! (all && null != audienceBuilder), "If audience is all, no any other audience may be set."); + Preconditions.checkArgument(! (all == false && null == audienceBuilder), "No any audience target is set."); + return new Audience(all, audienceBuilder); + } + } + +} + + diff --git a/src/main/java/com/ifish/jpush/push/model/audience/AudienceTarget.java b/src/main/java/com/ifish/jpush/push/model/audience/AudienceTarget.java new file mode 100644 index 0000000..8f72326 --- /dev/null +++ b/src/main/java/com/ifish/jpush/push/model/audience/AudienceTarget.java @@ -0,0 +1,121 @@ +package com.ifish.jpush.push.model.audience; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonPrimitive; +import com.ifish.jpush.push.model.PushModel; +import com.ifish.jpush.utils.Preconditions; + +public class AudienceTarget implements PushModel { + private final AudienceType audienceType; + private final Set values; + + private AudienceTarget(AudienceType audienceType, Set values) { + this.audienceType = audienceType; + this.values = values; + } + + public static Builder newBuilder() { + return new Builder(); + } + + public static AudienceTarget tag(String... tag) { + return newBuilder().setAudienceType(AudienceType.TAG).addAudienceTargetValues(tag).build(); + } + + public static AudienceTarget tag(Collection tags) { + return newBuilder().setAudienceType(AudienceType.TAG).addAudienceTargetValues(tags).build(); + } + + public static AudienceTarget tag_and(String... tag) { + return newBuilder().setAudienceType(AudienceType.TAG_AND).addAudienceTargetValues(tag).build(); + } + + public static AudienceTarget tag_and(Collection tags) { + return newBuilder().setAudienceType(AudienceType.TAG_AND).addAudienceTargetValues(tags).build(); + } + + public static AudienceTarget alias(String... alias) { + return newBuilder().setAudienceType(AudienceType.ALIAS).addAudienceTargetValues(alias).build(); + } + + public static AudienceTarget alias(Collection aliases) { + return newBuilder().setAudienceType(AudienceType.ALIAS).addAudienceTargetValues(aliases).build(); + } + + public static AudienceTarget registrationId(String... registrationId) { + return newBuilder().setAudienceType(AudienceType.REGISTRATION_ID).addAudienceTargetValues(registrationId).build(); + } + + public static AudienceTarget registrationId(Collection registrationIds) { + return newBuilder().setAudienceType(AudienceType.REGISTRATION_ID).addAudienceTargetValues(registrationIds).build(); + } + + + public AudienceType getAudienceType() { + return this.audienceType; + } + + public String getAudienceTypeValue() { + return this.audienceType.value(); + } + + public JsonElement toJSON() { + JsonArray array = new JsonArray(); + if (null != values) { + for (String value : values) { + array.add(new JsonPrimitive(value)); + } + } + return array; + } + + + public static class Builder { + private AudienceType audienceType = null; + private Set valueBuilder = null; + + public Builder setAudienceType(AudienceType audienceType) { + this.audienceType = audienceType; + return this; + } + + public Builder addAudienceTargetValue(String value) { + if (null == valueBuilder) { + valueBuilder = new HashSet(); + } + valueBuilder.add(value); + return this; + } + + public Builder addAudienceTargetValues(Collection values) { + if (null == valueBuilder) { + valueBuilder = new HashSet(); + } + for (String value : values) { + valueBuilder.add(value); + } + return this; + } + + public Builder addAudienceTargetValues(String... values) { + if (null == valueBuilder) { + valueBuilder = new HashSet(); + } + for (String value : values) { + valueBuilder.add(value); + } + return this; + } + + public AudienceTarget build() { + Preconditions.checkArgument(null != audienceType, "AudienceType should be set."); + Preconditions.checkArgument(null != valueBuilder, "Target values should be set one at least."); + return new AudienceTarget(audienceType, valueBuilder); + } + } +} diff --git a/src/main/java/com/ifish/jpush/push/model/audience/AudienceType.java b/src/main/java/com/ifish/jpush/push/model/audience/AudienceType.java new file mode 100644 index 0000000..081be1a --- /dev/null +++ b/src/main/java/com/ifish/jpush/push/model/audience/AudienceType.java @@ -0,0 +1,19 @@ +package com.ifish.jpush.push.model.audience; + +public enum AudienceType { + TAG("tag"), + TAG_AND("tag_and"), + ALIAS("alias"), + SEGMENT("segment"), + REGISTRATION_ID("registration_id"); + + private final String value; + private AudienceType(final String value) { + this.value = value; + } + public String value() { + return this.value; + } + + +} diff --git a/src/main/java/com/ifish/jpush/push/model/notification/AndroidNotification.java b/src/main/java/com/ifish/jpush/push/model/notification/AndroidNotification.java new file mode 100644 index 0000000..25d3f8d --- /dev/null +++ b/src/main/java/com/ifish/jpush/push/model/notification/AndroidNotification.java @@ -0,0 +1,87 @@ +package com.ifish.jpush.push.model.notification; + +import java.util.Map; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; + +public class AndroidNotification extends PlatformNotification { + public static final String NOTIFICATION_ANDROID = "android"; + + private static final String TITLE = "title"; + private static final String BUILDER_ID = "builder_id"; + + private final String title; + private final int builderId; + + private AndroidNotification(Object alert, String title, int builderId, + Map extras, + Map numberExtras, + Map booleanExtras, + Map jsonExtras) { + super(alert, extras, numberExtras, booleanExtras, jsonExtras); + + this.title = title; + this.builderId = builderId; + } + + public static Builder newBuilder() { + return new Builder(); + } + + public static AndroidNotification alert(String alert) { + return newBuilder().setAlert(alert).build(); + } + + + @Override + public String getPlatform() { + return NOTIFICATION_ANDROID; + } + + @Override + public JsonElement toJSON() { + JsonObject json = super.toJSON().getAsJsonObject(); + + if (builderId > 0) { + json.add(BUILDER_ID, new JsonPrimitive(this.builderId)); + } + if (null != title) { + json.add(TITLE, new JsonPrimitive(title)); + } + + return json; + } + + + public static class Builder extends PlatformNotification.Builder { + private String title; + private int builderId; + + protected Builder getThis() { + return this; + } + + public Builder setTitle(String title) { + this.title = title; + return this; + } + + public Builder setBuilderId(int builderId) { + this.builderId = builderId; + return this; + } + + public Builder setAlert(Object alert) { + this.alert = alert; + return this; + } + + + public AndroidNotification build() { + return new AndroidNotification(alert, title, builderId, + extrasBuilder, numberExtrasBuilder, booleanExtrasBuilder, jsonExtrasBuilder); + } + } +} diff --git a/src/main/java/com/ifish/jpush/push/model/notification/IosAlert.java b/src/main/java/com/ifish/jpush/push/model/notification/IosAlert.java new file mode 100644 index 0000000..7c77271 --- /dev/null +++ b/src/main/java/com/ifish/jpush/push/model/notification/IosAlert.java @@ -0,0 +1,131 @@ +package com.ifish.jpush.push.model.notification; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import com.ifish.jpush.push.model.PushModel; +import com.ifish.jpush.utils.StringUtils; + +public class IosAlert implements PushModel { + + private final String title; + private final String body; + private final String title_loc_key; + private final String[] title_loc_args; + private final String action_loc_key; + private final String loc_key; + private final String[] loc_args; + private final String launch_image; + + private IosAlert(String title, String body, String title_loc_key, String[] title_loc_args, + String action_loc_key, String loc_key, String[] loc_args, String launch_image) { + this.title = title; + this.body = body; + this.title_loc_key = title_loc_key; + this.title_loc_args = title_loc_args; + this.action_loc_key = action_loc_key; + this.loc_key = loc_key; + this.loc_args = loc_args; + this.launch_image = launch_image; + } + + public static Builder newBuilder() { + return new Builder(); + } + + @Override + public JsonElement toJSON() { + JsonObject json = new JsonObject(); + + if( StringUtils.isNotEmpty(title) ) { + json.addProperty("title", title); + } + + if( StringUtils.isNotEmpty(body) ) { + json.addProperty("body", body); + } + + if( StringUtils.isNotEmpty(title_loc_key) ) { + json.addProperty("title-loc-key", title_loc_key); + if( null != title_loc_args && title_loc_args.length > 0 ) { + JsonArray args = new JsonArray(); + for(int i = 0; i < title_loc_args.length; i++) { + args.add(new JsonPrimitive(title_loc_args[i])); + } + json.add("title-loc-args", args); + } + } + + if( StringUtils.isNotEmpty(action_loc_key) ) { + json.addProperty("action-loc-key", action_loc_key); + } + + if( StringUtils.isNotEmpty(loc_key) ) { + json.addProperty("loc-key", loc_key); + if( null != loc_args && loc_args.length > 0 ) { + JsonArray args = new JsonArray(); + for(int i = 0; i < loc_args.length; i++) { + args.add(new JsonPrimitive(loc_args[i])); + } + json.add("loc-args", args); + } + } + + if( StringUtils.isNotEmpty(launch_image) ) { + json.addProperty("launch-image", launch_image); + } + + return json; + } + + @Override + public String toString() { + return gson.toJson(toJSON()); + } + + public static class Builder { + private String title; + private String body; + private String title_loc_key; + private String[] title_loc_args; + private String action_loc_key; + private String loc_key; + private String[] loc_args; + private String launch_image; + + public Builder setTitleAndBody(String title, String body){ + this.title = title; + this.body = body; + return this; + } + + public Builder setTitleLoc(String title_loc_key, String... title_loc_args) { + this.title_loc_key = title_loc_key; + this.title_loc_args = title_loc_args; + return this; + } + + public Builder setActionLocKey(String action_loc_key) { + this.action_loc_key = action_loc_key; + return this; + } + + public Builder setLoc(String loc_key, String... loc_args) { + this.loc_key = loc_key; + this.loc_args = loc_args; + return this; + } + + public Builder setLaunchImage(String launch_image) { + this.launch_image = launch_image; + return this; + } + + public IosAlert build() { + return new IosAlert(title, body, title_loc_key, title_loc_args, action_loc_key, + loc_key, loc_args, launch_image); + } + } + +} diff --git a/src/main/java/com/ifish/jpush/push/model/notification/IosNotification.java b/src/main/java/com/ifish/jpush/push/model/notification/IosNotification.java new file mode 100644 index 0000000..f50674f --- /dev/null +++ b/src/main/java/com/ifish/jpush/push/model/notification/IosNotification.java @@ -0,0 +1,187 @@ +package com.ifish.jpush.push.model.notification; + +import java.util.Map; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import com.ifish.jpush.common.ServiceHelper; + +/** + * APNs 通知类 + *

    + * 支持 APNs 默认的几个参数: + *

  • alert: 继承自父类 PlatformNotification 的 alert 属性;本类设置则覆盖。
  • + *
  • badge: 支持 setBadge(int) 方法来设置;支持 incrBadge(int) 方法来增加。
  • + *
  • sound: 支持 setSound(string) 方法来设置声音文件。
  • + *
  • content-available: 用来支持后台推送。如果该值赋值为 1,表示开启后台推送。
  • + *
  • extras: JSON object. 支持更多的自定义字段信息。
  • + *

    + *

    + * 需要特别留意的是,JPush SDK 会对以下几个值有特别的默认设置考虑: + *

  • badge: 默认为 "+1"。如果需要取消 badge 值,需要显式地调用 disableBadge().
  • + *
  • sound: 默认为 "",即默认的声音提示。如果需要取消 sound 值,即不要声音,需要显式地调用 disableSound().
  • + *

    + */ +public class IosNotification extends PlatformNotification { + public static final String NOTIFICATION_IOS = "ios"; + + private static final String DEFAULT_SOUND = ""; + private static final String DEFAULT_BADGE = "+1"; + + private static final String BADGE = "badge"; + private static final String SOUND = "sound"; + private static final String CONTENT_AVAILABLE = "content-available"; + private static final String CATEGORY = "category"; + + private static final String ALERT_VALID_BADGE = "Badge number should be 0~99999, " + + "and can be prefixed with + to add, - to minus"; + + + private final boolean soundDisabled; + private final boolean badgeDisabled; + private final String sound; + private final String badge; + private final boolean contentAvailable; + private final String category; + + private IosNotification(Object alert, String sound, String badge, + boolean contentAvailable, boolean soundDisabled, boolean badgeDisabled, + String category, + Map extras, + Map numberExtras, + Map booleanExtras, + Map jsonExtras) { + super(alert, extras, numberExtras, booleanExtras, jsonExtras); + + this.sound = sound; + this.badge = badge; + this.contentAvailable = contentAvailable; + this.soundDisabled = soundDisabled; + this.badgeDisabled = badgeDisabled; + this.category = category; + } + + public static Builder newBuilder() { + return new Builder(); + } + + public static IosNotification alert(String alert) { + return newBuilder().setAlert(alert).build(); + } + + + @Override + public String getPlatform() { + return NOTIFICATION_IOS; + } + + @Override + public JsonElement toJSON() { + JsonObject json = super.toJSON().getAsJsonObject(); + + if (!badgeDisabled) { + if (null != badge) { + json.add(BADGE, new JsonPrimitive(this.badge)); + } else { + json.add(BADGE, new JsonPrimitive(DEFAULT_BADGE)); + } + } + if (!soundDisabled) { + if (null != sound) { + json.add(SOUND, new JsonPrimitive(sound)); + } else { + json.add(SOUND, new JsonPrimitive(DEFAULT_SOUND)); + } + } + if (contentAvailable) { + json.add(CONTENT_AVAILABLE, new JsonPrimitive(1)); + } + if (null != category) { + json.add(CATEGORY, new JsonPrimitive(category)); + } + + return json; + } + + + public static class Builder extends PlatformNotification.Builder { + private String sound; + private String badge; + private boolean contentAvailable = false; + private boolean soundDisabled = false; + private boolean badgeDisabled = false; + private String category; + + protected Builder getThis() { + return this; + } + + public Builder setSound(String sound) { + this.sound = sound; + return this; + } + + public Builder disableSound() { + this.soundDisabled = true; + return this; + } + + public Builder incrBadge(int badge) { + if (!ServiceHelper.isValidIntBadge(Math.abs(badge))) { + LOG.warn(ALERT_VALID_BADGE); + return this; + } + + if (badge >= 0) { + this.badge = "+" + badge; + } else { + this.badge = "" + badge; + } + return this; + } + + public Builder setBadge(int badge) { + if (!ServiceHelper.isValidIntBadge(badge)) { + LOG.warn(ALERT_VALID_BADGE); + return this; + } + this.badge = "" + badge; + return this; + } + + /** + * equals to: +1 + */ + public Builder autoBadge() { + return incrBadge(1); + } + + public Builder disableBadge() { + this.badgeDisabled = true; + return this; + } + + public Builder setContentAvailable(boolean contentAvailable) { + this.contentAvailable = contentAvailable; + return this; + } + + public Builder setCategory(String category) { + this.category = category; + return this; + } + + public Builder setAlert(Object alert) { + this.alert = alert; + return this; + } + + + public IosNotification build() { + return new IosNotification(alert, sound, badge, contentAvailable, + soundDisabled, badgeDisabled, category, + extrasBuilder, numberExtrasBuilder, booleanExtrasBuilder, jsonExtrasBuilder); + } + } +} diff --git a/src/main/java/com/ifish/jpush/push/model/notification/Notification.java b/src/main/java/com/ifish/jpush/push/model/notification/Notification.java new file mode 100644 index 0000000..bf44638 --- /dev/null +++ b/src/main/java/com/ifish/jpush/push/model/notification/Notification.java @@ -0,0 +1,163 @@ +package com.ifish.jpush.push.model.notification; + +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import com.ifish.jpush.push.model.PushModel; +import com.ifish.jpush.utils.Preconditions; + +public class Notification implements PushModel { + private final Object alert; + private final Set notifications; + + private Notification(Object alert, Set notifications) { + this.alert = alert; + this.notifications = notifications; + } + + public static Builder newBuilder() { + return new Builder(); + } + + /** + * Quick set all platform alert. + * Platform notification can override this alert. + * + * @param alert Notification alert + * @return first level notification object + */ + public static Notification alert(Object alert) { + return newBuilder().setAlert(alert).build(); + } + + /** + * shortcut + */ + public static Notification android(String alert, String title, Map extras) { + return newBuilder() + .addPlatformNotification(AndroidNotification.newBuilder() + .setAlert(alert) + .setTitle(title) + .setBuilderId(1) + .addExtras(extras) + .build()) + .build(); + } + + /** + * shortcut + */ + public static Notification ios(Object alert, Map extras) { + return newBuilder() + .addPlatformNotification(IosNotification.newBuilder() + .setAlert(alert) + .setSound("default") + .setCategory("INVITE_CATEGORY") + .addExtras(extras) + .build()) + .build(); + } + + /** + * shortcut + */ + public static Notification ios_auto_badge() { + return newBuilder() + .addPlatformNotification(IosNotification.newBuilder() + .setAlert("") + .autoBadge() + .build()) + .build(); + } + + /** + * shortcut + */ + public static Notification ios_set_badge(int badge) { + return newBuilder() + .addPlatformNotification(IosNotification.newBuilder() + .setAlert("") + .setBadge(badge) + .build()) + .build(); + } + + /** + * shortcut + */ + public static Notification ios_incr_badge(int badge) { + return newBuilder() + .addPlatformNotification(IosNotification.newBuilder() + .setAlert("") + .incrBadge(badge) + .build()) + .build(); + } + + /** + * shortcut + */ + public static Notification winphone(String alert, Map extras) { + return newBuilder() + .addPlatformNotification(WinphoneNotification.newBuilder() + .setAlert(alert) + .addExtras(extras) + .build()) + .build(); + } + + public JsonElement toJSON() { + JsonObject json = new JsonObject(); + if (null != alert) { + if(alert instanceof JsonObject) { + json.add(PlatformNotification.ALERT, (JsonObject) alert); + } else if (alert instanceof IosAlert) { + json.add(PlatformNotification.ALERT, ((IosAlert) alert).toJSON()); + } else { + json.add(PlatformNotification.ALERT, new JsonPrimitive(alert.toString())); + } + } + if (null != notifications) { + for (PlatformNotification pn : notifications) { + if (this.alert != null && pn.getAlert() == null) { + pn.setAlert(this.alert); + } + + Preconditions.checkArgument(! (null == pn.getAlert()), + "For any platform notification, alert field is needed. It can be empty string."); + + json.add(pn.getPlatform(), pn.toJSON()); + } + } + return json; + } + + public static class Builder { + private Object alert; + private Set builder; + + public Builder setAlert(Object alert) { + this.alert = alert; + return this; + } + + public Builder addPlatformNotification(PlatformNotification notification) { + if (null == builder) { + builder = new HashSet(); + } + builder.add(notification); + return this; + } + + public Notification build() { + Preconditions.checkArgument(! (null == builder && null == alert), + "No notification payload is set."); + return new Notification(alert, builder); + } + } +} + diff --git a/src/main/java/com/ifish/jpush/push/model/notification/PlatformNotification.java b/src/main/java/com/ifish/jpush/push/model/notification/PlatformNotification.java new file mode 100644 index 0000000..ea18499 --- /dev/null +++ b/src/main/java/com/ifish/jpush/push/model/notification/PlatformNotification.java @@ -0,0 +1,199 @@ +package com.ifish.jpush.push.model.notification; + +import java.util.HashMap; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import com.ifish.jpush.push.model.PushModel; +import com.ifish.jpush.utils.Preconditions; + +public abstract class PlatformNotification implements PushModel { + public static final String ALERT = "alert"; + private static final String EXTRAS = "extras"; + + protected static final Logger LOG = LoggerFactory.getLogger(PlatformNotification.class); + + private Object alert; + private final Map extras; + private final Map numberExtras; + private final Map booleanExtras; + private final Map jsonExtras; + + public PlatformNotification(Object alert, Map extras, + Map numberExtras, + Map booleanExtras, + Map jsonExtras) { + this.alert = alert; + this.extras = extras; + this.numberExtras = numberExtras; + this.booleanExtras = booleanExtras; + this.jsonExtras = jsonExtras; + } + + @Override + public JsonElement toJSON() { + JsonObject json = new JsonObject(); + + if (null != alert) { + if ( alert instanceof JsonObject) { + json.add(ALERT, (JsonObject) alert); + } else if (alert instanceof IosAlert) { + json.add(ALERT, ((IosAlert) alert).toJSON()); + } else { + json.add(ALERT, new JsonPrimitive(alert.toString())); + } + } + + JsonObject extrasObject = null; + if (null != extras || null != numberExtras || null != booleanExtras || null != jsonExtras) { + extrasObject = new JsonObject(); + } + + if (null != extras) { + String value = null; + for (String key : extras.keySet()) { + value = extras.get(key); + if (null != value) { + extrasObject.add(key, new JsonPrimitive(value)); + } + } + } + if (null != numberExtras) { + Number value = null; + for (String key : numberExtras.keySet()) { + value = numberExtras.get(key); + if (null != value) { + extrasObject.add(key, new JsonPrimitive(value)); + } + } + } + if (null != booleanExtras) { + Boolean value = null; + for (String key : booleanExtras.keySet()) { + value = booleanExtras.get(key); + if (null != value) { + extrasObject.add(key, new JsonPrimitive(value)); + } + } + } + if (null != jsonExtras) { + JsonObject value = null; + for (String key : jsonExtras.keySet()) { + value = jsonExtras.get(key); + if (null != value) { + extrasObject.add(key, value); + } + } + } + + if (null != extras || null != numberExtras || null != booleanExtras || null != jsonExtras) { + json.add(EXTRAS, extrasObject); + } + + return json; + } + + protected Object getAlert() { + return this.alert; + } + + protected void setAlert(Object alert) { + this.alert = alert; + } + + protected abstract String getPlatform(); + + protected abstract static class Builder> { + private B theBuilder; + + protected Object alert; + protected Map extrasBuilder; + protected Map numberExtrasBuilder; + protected Map booleanExtrasBuilder; + protected Map jsonExtrasBuilder; + + public Builder () { + theBuilder = getThis(); + } + + protected abstract B getThis(); + + public abstract B setAlert(Object alert); + + public B addExtra(String key, String value) { + Preconditions.checkArgument(! (null == key), "Key should not be null."); + if (null == value) { + LOG.debug("Extra value is null, throw away it."); + return theBuilder; + } + if (null == extrasBuilder) { + extrasBuilder = new HashMap(); + } + extrasBuilder.put(key, value); + return theBuilder; + } + + public B addExtras(Map extras) { + if (null == extras) { + LOG.warn("Null extras param. Throw away it."); + return theBuilder; + } + + if (null == extrasBuilder) { + extrasBuilder = new HashMap(); + } + for (String key : extras.keySet()) { + extrasBuilder.put(key, extras.get(key)); + } + return theBuilder; + } + + public B addExtra(String key, Number value) { + Preconditions.checkArgument(! (null == key), "Key should not be null."); + if (null == value) { + LOG.debug("Extra value is null, throw away it."); + return theBuilder; + } + if (null == numberExtrasBuilder) { + numberExtrasBuilder = new HashMap(); + } + numberExtrasBuilder.put(key, value); + return theBuilder; + } + + public B addExtra(String key, Boolean value) { + Preconditions.checkArgument(! (null == key), "Key should not be null."); + if (null == value) { + LOG.debug("Extra value is null, throw away it."); + return theBuilder; + } + if (null == booleanExtrasBuilder) { + booleanExtrasBuilder = new HashMap(); + } + booleanExtrasBuilder.put(key, value); + return theBuilder; + } + + public B addExtra(String key, JsonObject value) { + Preconditions.checkArgument(! (null == key), "Key should not be null."); + if (null == value) { + LOG.debug("Extra value is null, throw away it."); + return theBuilder; + } + if (null == jsonExtrasBuilder) { + jsonExtrasBuilder = new HashMap(); + } + jsonExtrasBuilder.put(key, value); + return theBuilder; + } + + public abstract T build(); + } + + +} diff --git a/src/main/java/com/ifish/jpush/push/model/notification/WinphoneNotification.java b/src/main/java/com/ifish/jpush/push/model/notification/WinphoneNotification.java new file mode 100644 index 0000000..c28caa4 --- /dev/null +++ b/src/main/java/com/ifish/jpush/push/model/notification/WinphoneNotification.java @@ -0,0 +1,87 @@ +package com.ifish.jpush.push.model.notification; + +import java.util.Map; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; + +public class WinphoneNotification extends PlatformNotification { + private static final String NOTIFICATION_WINPHONE = "winphone"; + + private static final String TITLE = "title"; + private static final String _OPEN_PAGE = "_open_page"; + + private final String title; + private final String openPage; + + private WinphoneNotification(Object alert, String title, String openPage, + Map extras, + Map numberExtras, + Map booleanExtras, + Map jsonExtras) { + super(alert, extras, numberExtras, booleanExtras, jsonExtras); + + this.title = title; + this.openPage = openPage; + } + + public static Builder newBuilder() { + return new Builder(); + } + + public static WinphoneNotification alert(String alert) { + return newBuilder().setAlert(alert).build(); + } + + + @Override + public String getPlatform() { + return NOTIFICATION_WINPHONE; + } + + @Override + public JsonElement toJSON() { + JsonObject json = super.toJSON().getAsJsonObject(); + + if (null != title) { + json.add(TITLE, new JsonPrimitive(title)); + } + if (null != openPage) { + json.add(_OPEN_PAGE, new JsonPrimitive(openPage)); + } + + return json; + } + + + public static class Builder extends PlatformNotification.Builder { + private String title; + private String openPage; + + protected Builder getThis() { + return this; + } + + public Builder setTitle(String title) { + this.title = title; + return this; + } + + public Builder setOpenPage(String openPage) { + this.openPage = openPage; + return this; + } + + public Builder setAlert(Object alert) { + this.alert = alert; + return this; + } + + + public WinphoneNotification build() { + return new WinphoneNotification(alert, title, openPage, + extrasBuilder, numberExtrasBuilder, booleanExtrasBuilder, jsonExtrasBuilder); + } + } +} diff --git a/src/main/java/com/ifish/jpush/report/MessagesResult.java b/src/main/java/com/ifish/jpush/report/MessagesResult.java new file mode 100644 index 0000000..98c1561 --- /dev/null +++ b/src/main/java/com/ifish/jpush/report/MessagesResult.java @@ -0,0 +1,50 @@ +package com.ifish.jpush.report; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.List; + +import com.google.gson.annotations.Expose; +import com.google.gson.reflect.TypeToken; +import com.ifish.jpush.common.resp.BaseResult; +import com.ifish.jpush.common.resp.ResponseWrapper; + +public class MessagesResult extends BaseResult { + private static final Type MESSAGE_TYPE = new TypeToken>(){}.getType(); + + @Expose public List messages = new ArrayList(); + + public static class Message { + @Expose public long msg_id; + @Expose public Android android; + @Expose public Ios ios; + } + + public static class Android { + @Expose public int received; + @Expose public int target; + @Expose public int online_push; + @Expose public int click; + @Expose public int msg_click; + } + + public static class Ios { + @Expose public int apns_sent; + @Expose public int apns_target; + @Expose public int click; + @Expose public int target; + @Expose public int received; + @Expose public int msg_click; + } + + static MessagesResult fromResponse(ResponseWrapper responseWrapper) { + MessagesResult result = new MessagesResult(); + if (responseWrapper.isServerResponse()) { + result.messages = _gson.fromJson(responseWrapper.responseContent, MESSAGE_TYPE); + } + + result.setResponseWrapper(responseWrapper); + return result; + } + +} diff --git a/src/main/java/com/ifish/jpush/report/ReceivedsResult.java b/src/main/java/com/ifish/jpush/report/ReceivedsResult.java new file mode 100644 index 0000000..dfe1968 --- /dev/null +++ b/src/main/java/com/ifish/jpush/report/ReceivedsResult.java @@ -0,0 +1,34 @@ +package com.ifish.jpush.report; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.List; + +import com.google.gson.annotations.Expose; +import com.google.gson.reflect.TypeToken; +import com.ifish.jpush.common.resp.BaseResult; +import com.ifish.jpush.common.resp.ResponseWrapper; + +public class ReceivedsResult extends BaseResult { + private static final Type RECEIVED_TYPE = new TypeToken>(){}.getType(); + + @Expose public List received_list = new ArrayList(); + + + public static class Received { + @Expose public long msg_id; + @Expose public int android_received; + @Expose public int ios_apns_sent; + } + + static ReceivedsResult fromResponse(ResponseWrapper responseWrapper) { + ReceivedsResult result = new ReceivedsResult(); + if (responseWrapper.isServerResponse()) { + result.received_list = _gson.fromJson(responseWrapper.responseContent, RECEIVED_TYPE); + } + + result.setResponseWrapper(responseWrapper); + return result; + } + +} diff --git a/src/main/java/com/ifish/jpush/report/ReportClient.java b/src/main/java/com/ifish/jpush/report/ReportClient.java new file mode 100644 index 0000000..84adff3 --- /dev/null +++ b/src/main/java/com/ifish/jpush/report/ReportClient.java @@ -0,0 +1,126 @@ +package com.ifish.jpush.report; + +import java.net.URLEncoder; +import java.util.regex.Pattern; + +import com.ifish.jpush.common.ClientConfig; +import com.ifish.jpush.common.ServiceHelper; +import com.ifish.jpush.common.TimeUnit; +import com.ifish.jpush.common.connection.HttpProxy; +import com.ifish.jpush.common.connection.IHttpClient; +import com.ifish.jpush.common.connection.NativeHttpClient; +import com.ifish.jpush.common.resp.APIConnectionException; +import com.ifish.jpush.common.resp.APIRequestException; +import com.ifish.jpush.common.resp.BaseResult; +import com.ifish.jpush.common.resp.ResponseWrapper; +import com.ifish.jpush.utils.StringUtils; + +public class ReportClient { + + private final NativeHttpClient _httpClient; + private String _hostName; + private String _receivePath; + private String _userPath; + private String _messagePath; + + public ReportClient(String masterSecret, String appKey) { + this(masterSecret, appKey, IHttpClient.DEFAULT_MAX_RETRY_TIMES, null); + } + + public ReportClient(String masterSecret, String appKey, int maxRetryTimes) { + this(masterSecret, appKey, maxRetryTimes, null); + } + + public ReportClient(String masterSecret, String appKey, int maxRetryTimes, HttpProxy proxy) { + this(masterSecret, appKey, maxRetryTimes, proxy, ClientConfig.getInstance()); + } + + public ReportClient(String masterSecret, String appKey, int maxRetryTimes, HttpProxy proxy, ClientConfig conf) { + ServiceHelper.checkBasic(appKey, masterSecret); + + _hostName = (String) conf.get(ClientConfig.REPORT_HOST_NAME); + _receivePath = (String) conf.get(ClientConfig.REPORT_RECEIVE_PATH); + _userPath = (String) conf.get(ClientConfig.REPORT_USER_PATH); + _messagePath = (String) conf.get(ClientConfig.REPORT_MESSAGE_PATH); + + String authCode = ServiceHelper.getBasicAuthorization(appKey, masterSecret); + _httpClient = new NativeHttpClient(authCode, maxRetryTimes, proxy); + } + + + public ReceivedsResult getReceiveds(String[] msgIdArray) + throws APIConnectionException, APIRequestException { + return getReceiveds(StringUtils.arrayToString(msgIdArray)); + } + + public ReceivedsResult getReceiveds(String msgIds) + throws APIConnectionException, APIRequestException { + checkMsgids(msgIds); + + String url = _hostName + _receivePath + "?msg_ids=" + msgIds; + ResponseWrapper response = _httpClient.sendGet(url); + + return ReceivedsResult.fromResponse(response); + } + + public MessagesResult getMessages(String msgIds) + throws APIConnectionException, APIRequestException { + checkMsgids(msgIds); + + String url = _hostName + _messagePath + "?msg_ids=" + msgIds; + ResponseWrapper response = _httpClient.sendGet(url); + + return MessagesResult.fromResponse(response); + } + + public UsersResult getUsers(TimeUnit timeUnit, String start, int duration) + throws APIConnectionException, APIRequestException { + String startEncoded = null; + try { + startEncoded = URLEncoder.encode(start, "utf-8"); + } catch (Exception e) { + } + + String url = _hostName + _userPath + + "?time_unit=" + timeUnit.toString() + + "&start=" + startEncoded + "&duration=" + duration; + ResponseWrapper response = _httpClient.sendGet(url); + + return BaseResult.fromResponse(response, UsersResult.class); + } + + + private final static Pattern MSGID_PATTERNS = Pattern.compile("[^0-9, ]"); + + public static void checkMsgids(String msgIds) { + if (StringUtils.isTrimedEmpty(msgIds)) { + throw new IllegalArgumentException("msgIds param is required."); + } + + if (MSGID_PATTERNS.matcher(msgIds).find()) { + throw new IllegalArgumentException("msgIds param format is incorrect. " + + "It should be msg_id (number) which response from JPush Push API. " + + "If there are many, use ',' as interval. "); + } + + msgIds = msgIds.trim(); + if (msgIds.endsWith(",")) { + msgIds = msgIds.substring(0, msgIds.length() - 1); + } + + String[] splits = msgIds.split(","); + try { + for (String s : splits) { + s = s.trim(); + if (!StringUtils.isEmpty(s)) { + Long.parseLong(s); + } + } + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Every msg_id should be valid Long number which splits by ','"); + } + } + +} + + diff --git a/src/main/java/com/ifish/jpush/report/UsersResult.java b/src/main/java/com/ifish/jpush/report/UsersResult.java new file mode 100644 index 0000000..a006513 --- /dev/null +++ b/src/main/java/com/ifish/jpush/report/UsersResult.java @@ -0,0 +1,39 @@ +package com.ifish.jpush.report; + +import java.util.ArrayList; +import java.util.List; + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; +import com.ifish.jpush.common.TimeUnit; +import com.ifish.jpush.common.resp.BaseResult; + +public class UsersResult extends BaseResult { + + @Expose public TimeUnit time_unit; + @Expose public String start; + @Expose public int duration; + @Expose public List items = new ArrayList(); + + + public static class User { + @Expose public String time; + @Expose public Android android; + @Expose public Ios ios; + } + + public static class Android { + @SerializedName("new") @Expose public long add; + @Expose public int online; + @Expose public int active; + } + + public static class Ios { + @SerializedName("new") @Expose public long add; + @Expose public int online; + @Expose public int active; + } + +} + + diff --git a/src/main/java/com/ifish/jpush/schedule/ScheduleClient.java b/src/main/java/com/ifish/jpush/schedule/ScheduleClient.java new file mode 100644 index 0000000..31795d9 --- /dev/null +++ b/src/main/java/com/ifish/jpush/schedule/ScheduleClient.java @@ -0,0 +1,97 @@ +package com.ifish.jpush.schedule; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.ifish.jpush.common.ClientConfig; +import com.ifish.jpush.common.ServiceHelper; +import com.ifish.jpush.common.connection.HttpProxy; +import com.ifish.jpush.common.connection.IHttpClient; +import com.ifish.jpush.common.connection.NativeHttpClient; +import com.ifish.jpush.common.resp.APIConnectionException; +import com.ifish.jpush.common.resp.APIRequestException; +import com.ifish.jpush.common.resp.ResponseWrapper; +import com.ifish.jpush.schedule.model.SchedulePayload; +import com.ifish.jpush.utils.Preconditions; +import com.ifish.jpush.utils.StringUtils; + +public class ScheduleClient { + + private static final Logger LOG = LoggerFactory.getLogger(ScheduleClient.class); + private final NativeHttpClient _httpClient; + + private String hostName; + private String schedulePath; + + public ScheduleClient(String masterSecret, String appkey) { + this(masterSecret, appkey, IHttpClient.DEFAULT_MAX_RETRY_TIMES, null, ClientConfig.getInstance()); + } + + public ScheduleClient(String masterSecret, String appKey, int maxRetryTimes) { + this(masterSecret, appKey, maxRetryTimes, null, ClientConfig.getInstance()); + } + + public ScheduleClient(String masterSecret, String appKey, int maxRetryTimes, HttpProxy proxy) { + this(masterSecret, appKey, maxRetryTimes, proxy, ClientConfig.getInstance()); + } + + /** + * Create a Schedule Client with custom configuration. + * @param masterSecret API access secret of the appKey. + * @param appKey The KEY of one application on JPush. + * @param maxRetryTimes Max retry times + * @param proxy The proxy, if there is no proxy, should be null. + * @param conf The client configuration. Can use ClientConfig.getInstance() as default. + */ + public ScheduleClient(String masterSecret, String appKey, int maxRetryTimes, HttpProxy proxy, ClientConfig conf) { + ServiceHelper.checkBasic(appKey, masterSecret); + hostName = (String) conf.get(ClientConfig.SCHEDULE_HOST_NAME); + schedulePath = (String) conf.get(ClientConfig.SCHEDULE_PATH); + + String authCode = ServiceHelper.getBasicAuthorization(appKey, masterSecret); + this._httpClient = new NativeHttpClient(authCode, maxRetryTimes, proxy); + } + + public ScheduleResult createSchedule(SchedulePayload payload) throws APIConnectionException, APIRequestException { + + Preconditions.checkArgument(null != payload, "payload should not be null"); + + ResponseWrapper response = _httpClient.sendPost(hostName + schedulePath, payload.toString()); + return ScheduleResult.fromResponse(response, ScheduleResult.class); + } + + public ScheduleListResult getScheduleList(int page) throws APIConnectionException, APIRequestException{ + + Preconditions.checkArgument(page > 0, "page should more than 0."); + + ResponseWrapper response = _httpClient.sendGet(hostName + schedulePath + "?page=" + page); + return ScheduleListResult.fromResponse(response, ScheduleListResult.class); + } + + public ScheduleResult getSchedule(String scheduleId) throws APIConnectionException, APIRequestException{ + + Preconditions.checkArgument(StringUtils.isNotEmpty(scheduleId), "scheduleId should not be empty"); + + ResponseWrapper response = _httpClient.sendGet(hostName + schedulePath + "/" + scheduleId); + return ScheduleResult.fromResponse(response, ScheduleResult.class); + } + + public ScheduleResult updateSchedule(String scheduleId, SchedulePayload payload) throws APIConnectionException, APIRequestException{ + + Preconditions.checkArgument(StringUtils.isNotEmpty(scheduleId), "scheduleId should not be empty"); + Preconditions.checkArgument(null != payload, "payload should not be null"); + + ResponseWrapper response = _httpClient.sendPut(hostName + schedulePath + "/" + scheduleId, + payload.toString()); + return ScheduleResult.fromResponse(response, ScheduleResult.class); + } + + public void deleteSchedule(String scheduleId) throws APIConnectionException, APIRequestException{ + + Preconditions.checkArgument(StringUtils.isNotEmpty(scheduleId), "scheduleId should not be empty"); + + _httpClient.sendDelete(hostName + schedulePath + "/" + scheduleId); + } + + +} diff --git a/src/main/java/com/ifish/jpush/schedule/ScheduleListResult.java b/src/main/java/com/ifish/jpush/schedule/ScheduleListResult.java new file mode 100644 index 0000000..e7340bf --- /dev/null +++ b/src/main/java/com/ifish/jpush/schedule/ScheduleListResult.java @@ -0,0 +1,31 @@ +package com.ifish.jpush.schedule; + + +import java.util.List; + +import com.google.gson.annotations.Expose; +import com.ifish.jpush.common.resp.BaseResult; + +public class ScheduleListResult extends BaseResult{ + + @Expose int total_count; + @Expose int total_pages; + @Expose int page; + @Expose List schedules; + + public int getTotal_count() { + return total_count; + } + + public int getTotal_pages() { + return total_pages; + } + + public int getPage() { + return page; + } + + public List getSchedules() { + return schedules; + } +} diff --git a/src/main/java/com/ifish/jpush/schedule/ScheduleResult.java b/src/main/java/com/ifish/jpush/schedule/ScheduleResult.java new file mode 100644 index 0000000..3810fa6 --- /dev/null +++ b/src/main/java/com/ifish/jpush/schedule/ScheduleResult.java @@ -0,0 +1,34 @@ +package com.ifish.jpush.schedule; + +import com.google.gson.JsonObject; +import com.google.gson.annotations.Expose; +import com.ifish.jpush.common.resp.BaseResult; + +public class ScheduleResult extends BaseResult{ + + @Expose String schedule_id; + @Expose String name; + @Expose Boolean enabled; + @Expose JsonObject trigger; + @Expose JsonObject push; + + public String getSchedule_id() { + return schedule_id; + } + + public String getName() { + return name; + } + + public Boolean getEnabled() { + return enabled; + } + + public JsonObject getTrigger() { + return trigger; + } + + public JsonObject getPush() { + return push; + } +} diff --git a/src/main/java/com/ifish/jpush/schedule/model/IModel.java b/src/main/java/com/ifish/jpush/schedule/model/IModel.java new file mode 100644 index 0000000..dd943af --- /dev/null +++ b/src/main/java/com/ifish/jpush/schedule/model/IModel.java @@ -0,0 +1,8 @@ +package com.ifish.jpush.schedule.model; + +import com.google.gson.JsonElement; + +public interface IModel { + + public JsonElement toJSON(); +} diff --git a/src/main/java/com/ifish/jpush/schedule/model/SchedulePayload.java b/src/main/java/com/ifish/jpush/schedule/model/SchedulePayload.java new file mode 100644 index 0000000..33731d4 --- /dev/null +++ b/src/main/java/com/ifish/jpush/schedule/model/SchedulePayload.java @@ -0,0 +1,83 @@ +package com.ifish.jpush.schedule.model; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.ifish.jpush.push.model.PushPayload; +import com.ifish.jpush.utils.StringUtils; + +public class SchedulePayload implements IModel { + + private static Gson gson = new Gson(); + + private String name; + private Boolean enabled; + private TriggerPayload trigger; + private PushPayload push; + + private SchedulePayload(String name, Boolean enabled, TriggerPayload trigger, PushPayload push) { + this.name = name; + this.enabled = enabled; + this.trigger = trigger; + this.push = push; + } + + public static Builder newBuilder() { + return new Builder(); + } + + @Override + public JsonElement toJSON() { + JsonObject json = new JsonObject(); + if ( StringUtils.isNotEmpty(name) ) { + json.addProperty("name", name); + } + if ( null != enabled ) { + json.addProperty("enabled", enabled); + } + if ( null != trigger ) { + json.add("trigger", trigger.toJSON()); + } + if ( null != push ) { + json.add("push", push.toJSON()); + } + return json; + } + + @Override + public String toString() { + return gson.toJson(toJSON()); + } + + public static class Builder{ + private String name; + private Boolean enabled; + private TriggerPayload trigger; + private PushPayload push; + + public Builder setName(String name) { + this.name = name; + return this; + } + + public Builder setEnabled(Boolean enabled) { + this.enabled = enabled; + return this; + } + + public Builder setTrigger(TriggerPayload trigger) { + this.trigger = trigger; + return this; + } + + public Builder setPush(PushPayload push) { + this.push = push; + return this; + } + + public SchedulePayload build() { + + return new SchedulePayload(name, enabled, trigger, push); + } + } +} diff --git a/src/main/java/com/ifish/jpush/schedule/model/TriggerPayload.java b/src/main/java/com/ifish/jpush/schedule/model/TriggerPayload.java new file mode 100644 index 0000000..57fc477 --- /dev/null +++ b/src/main/java/com/ifish/jpush/schedule/model/TriggerPayload.java @@ -0,0 +1,175 @@ +package com.ifish.jpush.schedule.model; + +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import com.ifish.jpush.common.TimeUnit; +import com.ifish.jpush.utils.Preconditions; +import com.ifish.jpush.utils.StringUtils; +import com.ifish.jpush.utils.TimeUtils; + + +public class TriggerPayload implements IModel { + + private static Gson gson = new Gson(); + + private Type type; + + private String start; + private String end; + private String time; + private TimeUnit time_unit; + private int frequency; + private String[] point; + + private TriggerPayload(String time) { + this.type = Type.single; + this.time = time; + } + + private TriggerPayload(String start, String end, String time, TimeUnit time_unit, int frequency, String[] point) { + this.type = Type.periodical; + this.start = start; + this.end = end; + this.time = time; + this.time_unit = time_unit; + this.frequency = frequency; + this.point = point; + } + + public static Builder newBuilder() { + return new Builder(); + } + + @Override + public String toString() { + return gson.toJson(toJSON()); + } + + @Override + public JsonElement toJSON() { + JsonObject json = new JsonObject(); + switch (type) { + case single: + JsonObject s = new JsonObject(); + s.addProperty("time", time); + json.add(Type.single.name(), s); + break; + case periodical: + JsonObject p = new JsonObject(); + p.addProperty("start", start); + p.addProperty("end", end); + p.addProperty("time", time); + p.addProperty("time_unit", time_unit.name().toLowerCase()); + p.addProperty("frequency", frequency); + if( !TimeUnit.DAY.equals(time_unit) ) { + JsonArray array = new JsonArray(); + for (String aPoint : point) { + array.add(new JsonPrimitive(aPoint)); + } + p.add("point", array); + } + json.add(Type.periodical.name(), p); + break; + default: + // nothing + } + return json; + } + + public static enum Type { + single, periodical + } + + public static class Builder{ + + private String start; + private String end; + private String time; + private TimeUnit time_unit; + private int frequency; + private String[] point; + + /** + * Setup time for single trigger. + * @param time The execute time, format yyyy-MM-dd HH:mm:ss + * @return this Builder + */ + public Builder setSingleTime(String time) { + this.time = time; + return this; + } + + + /** + * Setup period for periodical trigger. + * @param start The start time, format yyyy-MM-dd HH:mm:ss + * @param end The end time, format yyyy-MM-dd HH:mm:ss + * @param time The execute time, format HH:mm:ss + * @return this Builder + */ + public Builder setPeriodTime(String start, String end, String time) { + this.start = start; + this.end = end; + this.time = time; + return this; + } + + /** + * Setup frequency for periodical trigger. + * @param time_unit The time unit, can be day, week or month. + * @param frequency The frequency cooperate with time unit, must between 1 and 100. + * @param point The time point cooperate with time unit. + * If time unit is day, the point should be null. + * If time unit is week, should be the abbreviation of the days. eg. {"MON", "TUE"} + * If time unit is month, should be the date of the days. eg. {"01", "03"} + * @return this Builder + */ + public Builder setTimeFrequency(TimeUnit time_unit, int frequency, String[] point) { + this.time_unit = time_unit; + this.frequency = frequency; + this.point = point; + return this; + } + + public TriggerPayload buildSingle() { + Preconditions.checkArgument(StringUtils.isNotEmpty(time), "The time must not be empty."); + Preconditions.checkArgument(TimeUtils.isDateFormat(time), "The time format is incorrect."); + return new TriggerPayload(time); + } + + public TriggerPayload buildPeriodical() { + Preconditions.checkArgument(StringUtils.isNotEmpty(start), "The start must not be empty."); + Preconditions.checkArgument(StringUtils.isNotEmpty(end), "The end must not be empty."); + Preconditions.checkArgument(StringUtils.isNotEmpty(time), "The time must not be empty."); + + Preconditions.checkArgument(TimeUtils.isDateFormat(start), "The start format is incorrect."); + Preconditions.checkArgument(TimeUtils.isDateFormat(end), "The end format is incorrect."); + Preconditions.checkArgument(TimeUtils.isTimeFormat(time), "The time format is incorrect."); + + Preconditions.checkNotNull(time_unit, "The time_unit must not be null."); + Preconditions.checkArgument(isTimeUnitOk(time_unit), "The time unit must be DAY, WEEK or MONTH."); + + Preconditions.checkArgument(frequency > 0 && frequency < 101, "The frequency must be a int between 1 and 100."); + + return new TriggerPayload(start, end, time, time_unit, frequency, point); + } + + private boolean isTimeUnitOk(TimeUnit timeUnit) { + switch (timeUnit) { + case HOUR: + return false; + case DAY: + case WEEK: + case MONTH: + return true; + default: + return false; + } + } + + } + +} diff --git a/src/main/java/com/ifish/jpush/utils/Base64.java b/src/main/java/com/ifish/jpush/utils/Base64.java new file mode 100644 index 0000000..0665370 --- /dev/null +++ b/src/main/java/com/ifish/jpush/utils/Base64.java @@ -0,0 +1,120 @@ +package com.ifish.jpush.utils; + +import java.io.CharArrayWriter; +import java.io.IOException; + +public class Base64 { + static final char[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" + .toCharArray(); + + public static char[] encode(byte[] content) { + CharArrayWriter cw = new CharArrayWriter(4 * content.length / 3); + + int idx = 0; + + int x = 0; + + for (int i = 0; i < content.length; ++i) { + if (idx == 0) + x = (content[i] & 0xFF) << 16; + else if (idx == 1) + x |= (content[i] & 0xFF) << 8; + else { + x |= content[i] & 0xFF; + } + + if (++idx == 3) { + cw.write(alphabet[(x >> 18)]); + cw.write(alphabet[(x >> 12 & 0x3F)]); + cw.write(alphabet[(x >> 6 & 0x3F)]); + cw.write(alphabet[(x & 0x3F)]); + + idx = 0; + } + } + + if (idx == 1) { + cw.write(alphabet[(x >> 18)]); + cw.write(alphabet[(x >> 12 & 0x3F)]); + cw.write(61); + cw.write(61); + } + + if (idx == 2) { + cw.write(alphabet[(x >> 18)]); + cw.write(alphabet[(x >> 12 & 0x3F)]); + cw.write(alphabet[(x >> 6 & 0x3F)]); + cw.write(61); + } + + return cw.toCharArray(); + } + + public static byte[] decode(char[] message) throws IOException { + byte[] buff = new byte[4]; + byte[] dest = new byte[message.length]; + + int bpos = 0; + int destpos = 0; + + for (int i = 0; i < message.length; ++i) { + int c = message[i]; + + if ((c != 10) && (c != 13) && (c != 32)) { + if (c == 9) + continue; + + if ((c >= 65) && (c <= 90)) { + buff[(bpos++)] = (byte) (c - 65); + } else if ((c >= 97) && (c <= 122)) { + buff[(bpos++)] = (byte) (c - 97 + 26); + } else if ((c >= 48) && (c <= 57)) { + buff[(bpos++)] = (byte) (c - 48 + 52); + } else if (c == 43) { + buff[(bpos++)] = 62; + } else if (c == 47) { + buff[(bpos++)] = 63; + } else if (c == 61) { + buff[(bpos++)] = 64; + } else { + throw new IOException("Illegal char in base64 code."); + } + + if (bpos == 4) { + bpos = 0; + + if (buff[0] == 64) + break; + + if (buff[1] == 64) + throw new IOException("Unexpected '=' in base64 code."); + + int v; + if (buff[2] == 64) { + v = (buff[0] & 0x3F) << 6 | buff[1] & 0x3F; + dest[(destpos++)] = (byte) (v >> 4); + break; + } + if (buff[3] == 64) { + v = (buff[0] & 0x3F) << 12 | (buff[1] & 0x3F) << 6 + | buff[2] & 0x3F; + dest[(destpos++)] = (byte) (v >> 10); + dest[(destpos++)] = (byte) (v >> 2); + break; + } + + v = (buff[0] & 0x3F) << 18 | (buff[1] & 0x3F) << 12 + | (buff[2] & 0x3F) << 6 | buff[3] & 0x3F; + dest[(destpos++)] = (byte) (v >> 16); + dest[(destpos++)] = (byte) (v >> 8); + dest[(destpos++)] = (byte) v; + } + } + } + + byte[] res = new byte[destpos]; + System.arraycopy(dest, 0, res, 0, destpos); + + return res; + } +} \ No newline at end of file diff --git a/src/main/java/com/ifish/jpush/utils/Nullable.java b/src/main/java/com/ifish/jpush/utils/Nullable.java new file mode 100644 index 0000000..2cdbb46 --- /dev/null +++ b/src/main/java/com/ifish/jpush/utils/Nullable.java @@ -0,0 +1,16 @@ +package com.ifish.jpush.utils; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Copied from javax.annotation.Nullable + */ +@Documented +//@TypeQualifierNickname +//@Nonnull(when = When.UNKNOWN) +@Retention(RetentionPolicy.RUNTIME) +public @interface Nullable { + +} diff --git a/src/main/java/com/ifish/jpush/utils/Preconditions.java b/src/main/java/com/ifish/jpush/utils/Preconditions.java new file mode 100644 index 0000000..fa88549 --- /dev/null +++ b/src/main/java/com/ifish/jpush/utils/Preconditions.java @@ -0,0 +1,439 @@ +/* + * Copyright (C) 2007 The Guava Authors + * + * 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.ifish.jpush.utils; + +/** + * Copied from Google Guava. + * + * Static convenience methods that help a method or constructor check whether it was invoked + * correctly (whether its preconditions have been met). These methods generally accept a + * {@code boolean} expression which is expected to be {@code true} (or in the case of {@code + * checkNotNull}, an object reference which is expected to be non-null). When {@code false} (or + * {@code null}) is passed instead, the {@code Preconditions} method throws an unchecked exception, + * which helps the calling method communicate to its caller that that caller has made + * a mistake. Example:
       {@code
    + *
    + *   /**
    + *    * Returns the positive square root of the given value.
    + *    *
    + *    * @throws IllegalArgumentException if the value is negative
    + *    *}{@code /
    + *   public static double sqrt(double value) {
    + *     Preconditions.checkArgument(value >= 0.0, "negative value: %s", value);
    + *     // calculate the square root
    + *   }
    + *
    + *   void exampleBadCaller() {
    + *     double d = sqrt(-1.0);
    + *   }}
    + * + * In this example, {@code checkArgument} throws an {@code IllegalArgumentException} to indicate + * that {@code exampleBadCaller} made an error in its call to {@code sqrt}. + * + *

    Warning about performance

    + * + *

    The goal of this class is to improve readability of code, but in some circumstances this may + * come at a significant performance cost. Remember that parameter values for message construction + * must all be computed eagerly, and autoboxing and varargs array creation may happen as well, even + * when the precondition check then succeeds (as it should almost always do in production). In some + * circumstances these wasted CPU cycles and allocations can add up to a real problem. + * Performance-sensitive precondition checks can always be converted to the customary form: + *

       {@code
    + *
    + *   if (value < 0.0) {
    + *     throw new IllegalArgumentException("negative value: " + value);
    + *   }}
    + * + *

    Other types of preconditions

    + * + *

    Not every type of precondition failure is supported by these methods. Continue to throw + * standard JDK exceptions such as {@link java.util.NoSuchElementException} or {@link + * UnsupportedOperationException} in the situations they are intended for. + * + *

    Non-preconditions

    + * + *

    It is of course possible to use the methods of this class to check for invalid conditions + * which are not the caller's fault. Doing so is not recommended because it is + * misleading to future readers of the code and of stack traces. See + * Conditional + * failures explained in the Guava User Guide for more advice. + * + *

    {@code java.util.Objects.requireNonNull()}

    + * + *

    Projects which use {@code com.google.common} should generally avoid the use of {@link + * java.util.Objects#requireNonNull(Object)}. Instead, use whichever of {@link + * #checkNotNull(Object)} or {@link Verify#verifyNotNull(Object)} is appropriate to the situation. + * (The same goes for the message-accepting overloads.) + * + *

    Only {@code %s} is supported

    + * + *

    In {@code Preconditions} error message template strings, only the {@code "%s"} specifier is + * supported, not the full range of {@link java.util.Formatter} specifiers. However, note that if + * the number of arguments does not match the number of occurrences of {@code "%s"} in the format + * string, {@code Preconditions} will still behave as expected, and will still include all argument + * values in the error message; the message will simply not be formatted exactly as intended. + * + *

    More information

    + * + *

    See the Guava User Guide on + * using {@code + * Preconditions}. + * + * @author Kevin Bourrillion + * @since 2.0 (imported from Google Collections Library) + */ +public final class Preconditions { + private Preconditions() {} + + /** + * Ensures the truth of an expression involving one or more parameters to the calling method. + * + * @param expression a boolean expression + * @throws IllegalArgumentException if {@code expression} is false + */ + public static void checkArgument(boolean expression) { + if (!expression) { + throw new IllegalArgumentException(); + } + } + + /** + * Ensures the truth of an expression involving one or more parameters to the calling method. + * + * @param expression a boolean expression + * @param errorMessage the exception message to use if the check fails; will be converted to a + * string using {@link String#valueOf(Object)} + * @throws IllegalArgumentException if {@code expression} is false + */ + public static void checkArgument(boolean expression, @Nullable Object errorMessage) { + if (!expression) { + throw new IllegalArgumentException(String.valueOf(errorMessage)); + } + } + + /** + * Ensures the truth of an expression involving one or more parameters to the calling method. + * + * @param expression a boolean expression + * @param errorMessageTemplate a template for the exception message should the check fail. The + * message is formed by replacing each {@code %s} placeholder in the template with an + * argument. These are matched by position - the first {@code %s} gets {@code + * errorMessageArgs[0]}, etc. Unmatched arguments will be appended to the formatted message + * in square braces. Unmatched placeholders will be left as-is. + * @param errorMessageArgs the arguments to be substituted into the message template. Arguments + * are converted to strings using {@link String#valueOf(Object)}. + * @throws IllegalArgumentException if {@code expression} is false + * @throws NullPointerException if the check fails and either {@code errorMessageTemplate} or + * {@code errorMessageArgs} is null (don't let this happen) + */ + public static void checkArgument(boolean expression, + @Nullable String errorMessageTemplate, + @Nullable Object... errorMessageArgs) { + if (!expression) { + throw new IllegalArgumentException(format(errorMessageTemplate, errorMessageArgs)); + } + } + + /** + * Ensures the truth of an expression involving the state of the calling instance, but not + * involving any parameters to the calling method. + * + * @param expression a boolean expression + * @throws IllegalStateException if {@code expression} is false + */ + public static void checkState(boolean expression) { + if (!expression) { + throw new IllegalStateException(); + } + } + + /** + * Ensures the truth of an expression involving the state of the calling instance, but not + * involving any parameters to the calling method. + * + * @param expression a boolean expression + * @param errorMessage the exception message to use if the check fails; will be converted to a + * string using {@link String#valueOf(Object)} + * @throws IllegalStateException if {@code expression} is false + */ + public static void checkState(boolean expression, @Nullable Object errorMessage) { + if (!expression) { + throw new IllegalStateException(String.valueOf(errorMessage)); + } + } + + /** + * Ensures the truth of an expression involving the state of the calling instance, but not + * involving any parameters to the calling method. + * + * @param expression a boolean expression + * @param errorMessageTemplate a template for the exception message should the check fail. The + * message is formed by replacing each {@code %s} placeholder in the template with an + * argument. These are matched by position - the first {@code %s} gets {@code + * errorMessageArgs[0]}, etc. Unmatched arguments will be appended to the formatted message + * in square braces. Unmatched placeholders will be left as-is. + * @param errorMessageArgs the arguments to be substituted into the message template. Arguments + * are converted to strings using {@link String#valueOf(Object)}. + * @throws IllegalStateException if {@code expression} is false + * @throws NullPointerException if the check fails and either {@code errorMessageTemplate} or + * {@code errorMessageArgs} is null (don't let this happen) + */ + public static void checkState(boolean expression, + @Nullable String errorMessageTemplate, + @Nullable Object... errorMessageArgs) { + if (!expression) { + throw new IllegalStateException(format(errorMessageTemplate, errorMessageArgs)); + } + } + + /** + * Ensures that an object reference passed as a parameter to the calling method is not null. + * + * @param reference an object reference + * @return the non-null reference that was validated + * @throws NullPointerException if {@code reference} is null + */ + public static T checkNotNull(T reference) { + if (reference == null) { + throw new NullPointerException(); + } + return reference; + } + + /** + * Ensures that an object reference passed as a parameter to the calling method is not null. + * + * @param reference an object reference + * @param errorMessage the exception message to use if the check fails; will be converted to a + * string using {@link String#valueOf(Object)} + * @return the non-null reference that was validated + * @throws NullPointerException if {@code reference} is null + */ + public static T checkNotNull(T reference, @Nullable Object errorMessage) { + if (reference == null) { + throw new NullPointerException(String.valueOf(errorMessage)); + } + return reference; + } + + /** + * Ensures that an object reference passed as a parameter to the calling method is not null. + * + * @param reference an object reference + * @param errorMessageTemplate a template for the exception message should the check fail. The + * message is formed by replacing each {@code %s} placeholder in the template with an + * argument. These are matched by position - the first {@code %s} gets {@code + * errorMessageArgs[0]}, etc. Unmatched arguments will be appended to the formatted message + * in square braces. Unmatched placeholders will be left as-is. + * @param errorMessageArgs the arguments to be substituted into the message template. Arguments + * are converted to strings using {@link String#valueOf(Object)}. + * @return the non-null reference that was validated + * @throws NullPointerException if {@code reference} is null + */ + public static T checkNotNull(T reference, + @Nullable String errorMessageTemplate, + @Nullable Object... errorMessageArgs) { + if (reference == null) { + // If either of these parameters is null, the right thing happens anyway + throw new NullPointerException(format(errorMessageTemplate, errorMessageArgs)); + } + return reference; + } + + /* + * All recent hotspots (as of 2009) *really* like to have the natural code + * + * if (guardExpression) { + * throw new BadException(messageExpression); + * } + * + * refactored so that messageExpression is moved to a separate String-returning method. + * + * if (guardExpression) { + * throw new BadException(badMsg(...)); + * } + * + * The alternative natural refactorings into void or Exception-returning methods are much slower. + * This is a big deal - we're talking factors of 2-8 in microbenchmarks, not just 10-20%. (This + * is a hotspot optimizer bug, which should be fixed, but that's a separate, big project). + * + * The coding pattern above is heavily used in java.util, e.g. in ArrayList. There is a + * RangeCheckMicroBenchmark in the JDK that was used to test this. + * + * But the methods in this class want to throw different exceptions, depending on the args, so it + * appears that this pattern is not directly applicable. But we can use the ridiculous, devious + * trick of throwing an exception in the middle of the construction of another exception. Hotspot + * is fine with that. + */ + + /** + * Ensures that {@code index} specifies a valid element in an array, list or string of size + * {@code size}. An element index may range from zero, inclusive, to {@code size}, exclusive. + * + * @param index a user-supplied index identifying an element of an array, list or string + * @param size the size of that array, list or string + * @return the value of {@code index} + * @throws IndexOutOfBoundsException if {@code index} is negative or is not less than {@code size} + * @throws IllegalArgumentException if {@code size} is negative + */ + public static int checkElementIndex(int index, int size) { + return checkElementIndex(index, size, "index"); + } + + /** + * Ensures that {@code index} specifies a valid element in an array, list or string of size + * {@code size}. An element index may range from zero, inclusive, to {@code size}, exclusive. + * + * @param index a user-supplied index identifying an element of an array, list or string + * @param size the size of that array, list or string + * @param desc the text to use to describe this index in an error message + * @return the value of {@code index} + * @throws IndexOutOfBoundsException if {@code index} is negative or is not less than {@code size} + * @throws IllegalArgumentException if {@code size} is negative + */ + public static int checkElementIndex( + int index, int size, @Nullable String desc) { + // Carefully optimized for execution by hotspot (explanatory comment above) + if (index < 0 || index >= size) { + throw new IndexOutOfBoundsException(badElementIndex(index, size, desc)); + } + return index; + } + + private static String badElementIndex(int index, int size, String desc) { + if (index < 0) { + return format("%s (%s) must not be negative", desc, index); + } else if (size < 0) { + throw new IllegalArgumentException("negative size: " + size); + } else { // index >= size + return format("%s (%s) must be less than size (%s)", desc, index, size); + } + } + + /** + * Ensures that {@code index} specifies a valid position in an array, list or string of + * size {@code size}. A position index may range from zero to {@code size}, inclusive. + * + * @param index a user-supplied index identifying a position in an array, list or string + * @param size the size of that array, list or string + * @return the value of {@code index} + * @throws IndexOutOfBoundsException if {@code index} is negative or is greater than {@code size} + * @throws IllegalArgumentException if {@code size} is negative + */ + public static int checkPositionIndex(int index, int size) { + return checkPositionIndex(index, size, "index"); + } + + /** + * Ensures that {@code index} specifies a valid position in an array, list or string of + * size {@code size}. A position index may range from zero to {@code size}, inclusive. + * + * @param index a user-supplied index identifying a position in an array, list or string + * @param size the size of that array, list or string + * @param desc the text to use to describe this index in an error message + * @return the value of {@code index} + * @throws IndexOutOfBoundsException if {@code index} is negative or is greater than {@code size} + * @throws IllegalArgumentException if {@code size} is negative + */ + public static int checkPositionIndex(int index, int size, @Nullable String desc) { + // Carefully optimized for execution by hotspot (explanatory comment above) + if (index < 0 || index > size) { + throw new IndexOutOfBoundsException(badPositionIndex(index, size, desc)); + } + return index; + } + + private static String badPositionIndex(int index, int size, String desc) { + if (index < 0) { + return format("%s (%s) must not be negative", desc, index); + } else if (size < 0) { + throw new IllegalArgumentException("negative size: " + size); + } else { // index > size + return format("%s (%s) must not be greater than size (%s)", desc, index, size); + } + } + + /** + * Ensures that {@code start} and {@code end} specify a valid positions in an array, list + * or string of size {@code size}, and are in order. A position index may range from zero to + * {@code size}, inclusive. + * + * @param start a user-supplied index identifying a starting position in an array, list or string + * @param end a user-supplied index identifying a ending position in an array, list or string + * @param size the size of that array, list or string + * @throws IndexOutOfBoundsException if either index is negative or is greater than {@code size}, + * or if {@code end} is less than {@code start} + * @throws IllegalArgumentException if {@code size} is negative + */ + public static void checkPositionIndexes(int start, int end, int size) { + // Carefully optimized for execution by hotspot (explanatory comment above) + if (start < 0 || end < start || end > size) { + throw new IndexOutOfBoundsException(badPositionIndexes(start, end, size)); + } + } + + private static String badPositionIndexes(int start, int end, int size) { + if (start < 0 || start > size) { + return badPositionIndex(start, size, "start index"); + } + if (end < 0 || end > size) { + return badPositionIndex(end, size, "end index"); + } + // end < start + return format("end index (%s) must not be less than start index (%s)", end, start); + } + + /** + * Substitutes each {@code %s} in {@code template} with an argument. These are matched by + * position: the first {@code %s} gets {@code args[0]}, etc. If there are more arguments than + * placeholders, the unmatched arguments will be appended to the end of the formatted message in + * square braces. + * + * @param template a non-null string containing 0 or more {@code %s} placeholders. + * @param args the arguments to be substituted into the message template. Arguments are converted + * to strings using {@link String#valueOf(Object)}. Arguments can be null. + */ + // Note that this is somewhat-improperly used from Verify.java as well. + static String format(String template, @Nullable Object... args) { + template = String.valueOf(template); // null -> "null" + + // start substituting the arguments into the '%s' placeholders + StringBuilder builder = new StringBuilder(template.length() + 16 * args.length); + int templateStart = 0; + int i = 0; + while (i < args.length) { + int placeholderStart = template.indexOf("%s", templateStart); + if (placeholderStart == -1) { + break; + } + builder.append(template.substring(templateStart, placeholderStart)); + builder.append(args[i++]); + templateStart = placeholderStart + 2; + } + builder.append(template.substring(templateStart)); + + // if we run out of placeholders, append the extra args in square braces + if (i < args.length) { + builder.append(" ["); + builder.append(args[i++]); + while (i < args.length) { + builder.append(", "); + builder.append(args[i++]); + } + builder.append(']'); + } + + return builder.toString(); + } +} diff --git a/src/main/java/com/ifish/jpush/utils/StringUtils.java b/src/main/java/com/ifish/jpush/utils/StringUtils.java new file mode 100644 index 0000000..63b8bff --- /dev/null +++ b/src/main/java/com/ifish/jpush/utils/StringUtils.java @@ -0,0 +1,89 @@ +package com.ifish.jpush.utils; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.security.MessageDigest; + + +public class StringUtils { + private final static String[] hexDigits = { "0", "1", "2", "3", "4", "5", + "6", "7", "8", "9", "A", "B", "C", "D", "E", "F" }; + + private static String byteArrayToHexString(byte[] b) { + StringBuffer resultSb = new StringBuffer(); + for (int i = 0; i < b.length; i++) { + resultSb.append(byteToHexString(b[i])); + } + return resultSb.toString(); + } + + private static String byteToHexString(byte b) { + int n = b; + if (n < 0) + n = 256 + n; + int d1 = n / 16; + int d2 = n % 16; + return hexDigits[d1] + hexDigits[d2]; + } + + public static String toMD5(String origin) { + String resultString = null; + try { + resultString = new String(origin); + MessageDigest md = MessageDigest.getInstance("MD5"); + resultString = byteArrayToHexString(md.digest(resultString.getBytes())); + } catch (Exception ex) { + ex.printStackTrace(); + } + return resultString; + } + + public static String encodeParam(String param) { + String encodeParam = null; + try { + encodeParam = URLEncoder.encode(param, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return encodeParam; + } + + public static String arrayToString(String[] values) { + if (null == values) return ""; + + StringBuffer buffer = new StringBuffer(values.length); + for (int i = 0; i < values.length; i++) { + buffer.append(values[i]).append(","); + } + if (buffer.length() > 0) { + return buffer.toString().substring(0, buffer.length() - 1); + } + return ""; + } + + public static boolean isEmpty(String s) { + return s == null || s.length() == 0; + } + + public static boolean isTrimedEmpty(String s) { + return s == null || s.trim().length() == 0; + } + + public static boolean isNotEmpty(String s) { + return s != null && s.length() > 0; + } + + public static boolean isLineBroken(String s) { + if ( null == s ) { + return false; + } + if (s.contains("\n")) { + return true; + } + if (s.contains("\r\n")) { + return true; + } + return false; + } + +} diff --git a/src/main/java/com/ifish/jpush/utils/TimeUtils.java b/src/main/java/com/ifish/jpush/utils/TimeUtils.java new file mode 100644 index 0000000..2934215 --- /dev/null +++ b/src/main/java/com/ifish/jpush/utils/TimeUtils.java @@ -0,0 +1,35 @@ +package com.ifish.jpush.utils; + + +import java.text.ParseException; +import java.text.SimpleDateFormat; + +public class TimeUtils { + + private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; + private static final String TIME_ONLY_FORMAT = "HH:mm:ss"; + + + public static boolean isDateFormat(String time) { + try { + SimpleDateFormat format = new SimpleDateFormat(DATE_FORMAT); + format.setLenient(false); + format.parse(time); + } catch (ParseException e) { + return false; + } + return true; + } + + public static boolean isTimeFormat(String time) { + try{ + SimpleDateFormat format = new SimpleDateFormat(TIME_ONLY_FORMAT); + format.setLenient(false); + format.parse(time); + } catch (ParseException e) { + return false; + } + return true; + } + +} diff --git a/src/main/java/com/ifish/netease/CheckSumBuilder.java b/src/main/java/com/ifish/netease/CheckSumBuilder.java new file mode 100644 index 0000000..3f3f12e --- /dev/null +++ b/src/main/java/com/ifish/netease/CheckSumBuilder.java @@ -0,0 +1,48 @@ +package com.ifish.netease; + +import java.security.MessageDigest; + +/** + * SHA1(AppSecret + Nonce + CurTime),三个参数拼接的字符串,进行SHA1哈希计算,转化成16进制字符(String,小写) + * @author Administrator + * + */ +public class CheckSumBuilder { + + // 计算并获取CheckSum + public static String getCheckSum(String appSecret, String nonce, String curTime) { + return encode("sha1", appSecret + nonce + curTime); + } + + // 计算并获取md5值 + public static String getMD5(String requestBody) { + return encode("md5", requestBody); + } + + private static String encode(String algorithm, String value) { + if (value == null) { + return null; + } + try { + MessageDigest messageDigest + = MessageDigest.getInstance(algorithm); + messageDigest.update(value.getBytes()); + return getFormattedText(messageDigest.digest()); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private static String getFormattedText(byte[] bytes) { + int len = bytes.length; + StringBuilder buf = new StringBuilder(len * 2); + for (int j = 0; j < len; j++) { + buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]); + buf.append(HEX_DIGITS[bytes[j] & 0x0f]); + } + return buf.toString(); + } + + private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + +} \ No newline at end of file diff --git a/src/main/java/com/ifish/netease/NeteaseIM.java b/src/main/java/com/ifish/netease/NeteaseIM.java new file mode 100644 index 0000000..b921731 --- /dev/null +++ b/src/main/java/com/ifish/netease/NeteaseIM.java @@ -0,0 +1,244 @@ +package com.ifish.netease; + +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.http.HttpResponse; +import org.apache.http.NameValuePair; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.ifish.enums.NeteaseEnum; +import com.ifish.util.IfishUtil; + +public class NeteaseIM { + + String appKey = ""; + String appSecret = ""; + + private static Logger log = LoggerFactory.getLogger(NeteaseIM.class); + + public NeteaseIM(String appKey,String appSecret){ + this.appKey=appKey; + this.appSecret=appSecret; + } + /** + * 创建云信ID + * @param accid 云信ID,最大长度32字符,必须保证一个APP内唯一 + * @param name 云信ID昵称,最大长度64字符,用来PUSH推送 时显示的昵称 + * @param icon 云信ID头像URL,第三方可选填,最大长度1024 + * @param props json属性,第三方可选填,最大长度1024字符 + * @return + * @throws Exception + */ + public Map createAccid(String accid,String name,String icon,String props){ + try { + DefaultHttpClient httpClient = new DefaultHttpClient(); + String url = "https://api.netease.im/nimserver/user/create.action"; + HttpPost httpPost = new HttpPost(url); + String nonce = IfishUtil.getCharAndNumr(10); + String curTime = String.valueOf((new Date()).getTime() / 1000L); + //计算CheckSum + String checkSum = CheckSumBuilder.getCheckSum(appSecret, nonce ,curTime); + //设置请求的header + httpPost.addHeader("AppKey", appKey); + httpPost.addHeader("Nonce", nonce); + httpPost.addHeader("CurTime", curTime); + httpPost.addHeader("CheckSum", checkSum); + httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8"); + //设置请求的参数 + List nvps = new ArrayList(); + nvps.add(new BasicNameValuePair("accid", accid)); + nvps.add(new BasicNameValuePair("name", name)); + nvps.add(new BasicNameValuePair("icon", icon)); + nvps.add(new BasicNameValuePair("props", props)); + httpPost.setEntity(new UrlEncodedFormEntity(nvps, "utf-8")); + //执行请求 + HttpResponse response = httpClient.execute(httpPost); + //执行结果 + String responseStr = EntityUtils.toString(response.getEntity(), "utf-8"); + JSONObject json = new JSONObject(responseStr); + String code = json.getString("code"); + Map map = new HashMap(); + map.put("code", code); + //200 + if(code.equals(NeteaseEnum.status200.getKey())){ + JSONObject infoJson = json.getJSONObject("info"); + String token = infoJson.getString("token"); + map.put("token", token); + } + else if(code.equals(NeteaseEnum.status414.getKey())){ + String desc = json.getString("desc"); + } + return map; + } catch (Exception e) { + log.error("CreateAccid error message:{},{}",accid,e.toString()); + } + return null; + } + /** + * 更新并获取新token + * @param accid + * @return + * @throws Exception + */ + public Map refreshToken(String accid){ + try { + DefaultHttpClient httpClient = new DefaultHttpClient(); + String url = "https://api.netease.im/nimserver/user/refreshToken.action"; + HttpPost httpPost = new HttpPost(url); + String nonce = IfishUtil.getCharAndNumr(10); + String curTime = String.valueOf((new Date()).getTime() / 1000L); + //计算CheckSum + String checkSum = CheckSumBuilder.getCheckSum(appSecret, nonce ,curTime); + //设置请求的header + httpPost.addHeader("AppKey", appKey); + httpPost.addHeader("Nonce", nonce); + httpPost.addHeader("CurTime", curTime); + httpPost.addHeader("CheckSum", checkSum); + httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8"); + //设置请求的参数 + List nvps = new ArrayList(); + nvps.add(new BasicNameValuePair("accid", accid)); + httpPost.setEntity(new UrlEncodedFormEntity(nvps, "utf-8")); + //执行请求 + HttpResponse response = httpClient.execute(httpPost); + //执行结果 + String responseStr = EntityUtils.toString(response.getEntity(), "utf-8"); + JSONObject json = new JSONObject(responseStr); + String code = json.getString("code"); + Map map = new HashMap(); + map.put("code", code); + //200 + if(code.equals(NeteaseEnum.status200.getKey())){ + JSONObject infoJson = json.getJSONObject("info"); + String token = infoJson.getString("token"); + map.put("token", token); + } + else if(code.equals(NeteaseEnum.status414.getKey())){ + String desc = json.getString("desc"); + } + return map; + } catch (Exception e) { + log.error("refreshToken error message:{},{}",accid,e.toString()); + } + return null; + } + + /** + * 发送普通消息 + * @param from + * @param to + * @param msg + * @return + */ + public Map sendMsg(String from,String to,String msg){ + try { + DefaultHttpClient httpClient = new DefaultHttpClient(); + String url = "https://api.netease.im/nimserver/msg/sendMsg.action"; + HttpPost httpPost = new HttpPost(url); + String nonce = IfishUtil.getCharAndNumr(10); + String curTime = String.valueOf((new Date()).getTime() / 1000L); + //计算CheckSum + String checkSum = CheckSumBuilder.getCheckSum(appSecret, nonce ,curTime); + //设置请求的header + httpPost.addHeader("AppKey", appKey); + httpPost.addHeader("Nonce", nonce); + httpPost.addHeader("CurTime", curTime); + httpPost.addHeader("CheckSum", checkSum); + httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8"); + //设置请求的参数 + List nvps = new ArrayList(); + nvps.add(new BasicNameValuePair("from", from)); + nvps.add(new BasicNameValuePair("to", to)); + nvps.add(new BasicNameValuePair("ope", "0")); + nvps.add(new BasicNameValuePair("type", "0")); + nvps.add(new BasicNameValuePair("body", "{\"msg\":\""+msg+"\"}")); + httpPost.setEntity(new UrlEncodedFormEntity(nvps, "utf-8")); + //执行请求 + HttpResponse response = httpClient.execute(httpPost); + //执行结果 + String responseStr = EntityUtils.toString(response.getEntity(), "utf-8"); + JSONObject json = new JSONObject(responseStr); + String code = json.getString("code"); + Map map = new HashMap(); + map.put("code", code); + //200 + if(code.equals(NeteaseEnum.status200.getKey())){ + + } + else if(code.equals(NeteaseEnum.status414.getKey())){ + String desc = json.getString("desc"); + } + return map; + } catch (Exception e) { + log.error("refreshToken error message:{}",e.toString()); + } + return null; + } + /** + * 批量发送点对点普通消息 + * @param fromAccid + * @param toAccids + * @param msg + * @return + */ + public Map sendBatchMsg(String fromAccid,String toAccids,String msg){ + try { + DefaultHttpClient httpClient = new DefaultHttpClient(); + String url = "https://api.netease.im/nimserver/msg/sendBatchMsg.action"; + HttpPost httpPost = new HttpPost(url); + String nonce = IfishUtil.getCharAndNumr(10); + String curTime = String.valueOf((new Date()).getTime() / 1000L); + //计算CheckSum + String checkSum = CheckSumBuilder.getCheckSum(appSecret, nonce ,curTime); + //设置请求的header + httpPost.addHeader("AppKey", appKey); + httpPost.addHeader("Nonce", nonce); + httpPost.addHeader("CurTime", curTime); + httpPost.addHeader("CheckSum", checkSum); + httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8"); + //设置请求的参数 + List nvps = new ArrayList(); + nvps.add(new BasicNameValuePair("fromAccid", fromAccid)); + nvps.add(new BasicNameValuePair("toAccids", toAccids)); + nvps.add(new BasicNameValuePair("type", "0")); + nvps.add(new BasicNameValuePair("body", "{\"msg\":\""+msg+"\"}")); + httpPost.setEntity(new UrlEncodedFormEntity(nvps, "utf-8")); + //执行请求 + HttpResponse response = httpClient.execute(httpPost); + //执行结果 + String responseStr = EntityUtils.toString(response.getEntity(), "utf-8"); + JSONObject json = new JSONObject(responseStr); + String code = json.getString("code"); + Map map = new HashMap(); + map.put("code", code); + //200 + if(code.equals(NeteaseEnum.status200.getKey())){ + + } + else if(code.equals(NeteaseEnum.status414.getKey())){ + String desc = json.getString("desc"); + } + return map; + } catch (Exception e) { + log.error("refreshToken error message:{}",e.toString()); + } + return null; + } + public static void main(String[] args) { + List list= new ArrayList(); + list.add("hello"); + list.add("hello1"); + new NeteaseIM("87b0e3315dfc2df08060bcb54246da68", "e62f6c247b46").createAccid("ifish", "爱鱼奇", "", ""); + } +} diff --git a/src/main/java/com/ifish/tianqi/javaDemo.java b/src/main/java/com/ifish/tianqi/javaDemo.java new file mode 100644 index 0000000..3288fc4 --- /dev/null +++ b/src/main/java/com/ifish/tianqi/javaDemo.java @@ -0,0 +1,107 @@ +package com.ifish.tianqi; + + +import javax.crypto.Mac; +import java.net.URLEncoder; +import java.security.InvalidKeyException; +import javax.crypto.spec.SecretKeySpec; + +public class javaDemo { + + private static final char last2byte = (char) Integer.parseInt("00000011", 2); + private static final char last4byte = (char) Integer.parseInt("00001111", 2); + private static final char last6byte = (char) Integer.parseInt("00111111", 2); + private static final char lead6byte = (char) Integer.parseInt("11111100", 2); + private static final char lead4byte = (char) Integer.parseInt("11110000", 2); + private static final char lead2byte = (char) Integer.parseInt("11000000", 2); + private static final char[] encodeTable = new char[] { 'A', 'B', 'C', 'D', + 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', + 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', + 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', + '4', '5', '6', '7', '8', '9', '+', '/' + }; + + public static String standardURLEncoder(String data, String key) { + byte[] byteHMAC = null; + String urlEncoder = ""; + try { + Mac mac = Mac.getInstance("HmacSHA1"); + SecretKeySpec spec = new SecretKeySpec(key.getBytes(), "HmacSHA1"); + mac.init(spec); + byteHMAC = mac.doFinal(data.getBytes()); + if (byteHMAC != null) { + String oauth = encode(byteHMAC); + if (oauth != null) { + urlEncoder = URLEncoder.encode(oauth, "utf8"); + } + } + } catch (InvalidKeyException e1) { + e1.printStackTrace(); + } catch (Exception e2) { + e2.printStackTrace(); + } + return urlEncoder; + } + + public static String encode(byte[] from) { + StringBuffer to = new StringBuffer((int) (from.length * 1.34) + 3); + int num = 0; + char currentByte = 0; + for (int i = 0; i < from.length; i++) { + num = num % 8; + while (num < 8) { + switch (num) { + case 0: + currentByte = (char) (from[i] & lead6byte); + currentByte = (char) (currentByte >>> 2); + break; + case 2: + currentByte = (char) (from[i] & last6byte); + break; + case 4: + currentByte = (char) (from[i] & last4byte); + currentByte = (char) (currentByte << 2); + if ((i + 1) < from.length) { + currentByte |= (from[i + 1] & lead2byte) >>> 6; + } + break; + case 6: + currentByte = (char) (from[i] & last2byte); + currentByte = (char) (currentByte << 4); + if ((i + 1) < from.length) { + currentByte |= (from[i + 1] & lead4byte) >>> 4; + } + break; + } + to.append(encodeTable[currentByte]); + num += 6; + } + } + if (to.length() % 4 != 0) { + for (int i = 4 - to.length() % 4; i > 0; i--) { + to.append("="); + } + } + return to.toString(); + } + + + public static void main(String[] args) { + try { + + //需要加密的数据 + String data = "http://open.weather.com.cn/data/?areaid=101020100&type=forecast_v&date=201603011100&appid=ee35072ca2850278"; + //密钥 + String key = "c4a99d_SmartWeatherAPI_a164e18"; + + String str = standardURLEncoder(data, key); + + System.out.println(str); + // http://open.weather.com.cn/data/?areaid=101020100&type=forecast_v&date=201603011100&appid=ee3507&key=WCD90OiAMNfP3g5qhdhXiUnyBnA%3D + + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/com/ifish/util/IfishUtil.java b/src/main/java/com/ifish/util/IfishUtil.java new file mode 100644 index 0000000..01904cf --- /dev/null +++ b/src/main/java/com/ifish/util/IfishUtil.java @@ -0,0 +1,56 @@ +package com.ifish.util; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Random; + +public class IfishUtil { + + private static final String formatDate1 ="yyyy-MM-dd"; + private static final String formatDate2 ="yyyy-MM-dd HH:mm:ss"; + + /** + * 格式化日期yyyy-MM-dd HH:mm:ss + * @param date + * @return + */ + public static String format2(Date date){ + SimpleDateFormat format = new SimpleDateFormat(formatDate2); + return format.format(date); + } + + /** + * 格式化日期yyyy-MM-dd + * @param date + * @return + */ + public static String format1(Date date){ + SimpleDateFormat format = new SimpleDateFormat(formatDate1); + return format.format(date); + } + + /** + * 随机生成字母与数字组合 + * @param length + * @return + */ + public static String getCharAndNumr(int length) { + String val = ""; + Random random = new Random(); + for (int i = 0; i < length; i++) { + // 输出字母还是数字 + String charOrNum = random.nextInt(2) % 2 == 0 ? "char" : "num"; + // 字符串 + if ("char".equalsIgnoreCase(charOrNum)) { + // 取得大写字母还是小写字母 + int choice = random.nextInt(2) % 2 == 0 ? 65 : 97; + val += (char) (choice + random.nextInt(26)); + // 数字 + } else if ("num".equalsIgnoreCase(charOrNum)) { + val += String.valueOf(random.nextInt(10)); + } + } + return val; + } + +} diff --git a/src/main/resources/jPpush.properties b/src/main/resources/jPpush.properties new file mode 100644 index 0000000..4c46f36 --- /dev/null +++ b/src/main/resources/jPpush.properties @@ -0,0 +1,16 @@ +#极光推送 +#appKey +jpush.android.appKey=d970d5e193cb2a0bbe41653c +#secret +jpush.android.secret=60162c8cf195ce9f4dc76629 +#production +jpush.android.productionMode=true +#appKey +jpush.ios.appKey=d147124018074eb970474e48 +#secret +jpush.ios.secret=a7d41825e75082b13675c326 +#production +jpush.ios.productionMode=true +#云信IM +netease.appKey=87b0e3315dfc2df08060bcb54246da68 +netease.appSecret=e62f6c247b46 diff --git a/src/main/resources/jdbc.properties b/src/main/resources/jdbc.properties new file mode 100644 index 0000000..f20d58c --- /dev/null +++ b/src/main/resources/jdbc.properties @@ -0,0 +1,32 @@ +c3p0.driverClassName=com.mysql.jdbc.Driver +c3p0.url=jdbc\:mysql\://localhost\:3306/myfishdb?characterEncoding\=UTF-8 +c3p0.username=ifish +c3p0.password=ifish7pwd +#c3p0.username=root +#c3p0.password=123456 + +c3p0.autoCommitOnClose=true +c3p0.initialPoolSize=50 +c3p0.minPoolSize=50 +c3p0.maxPoolSize=100 +c3p0.acquireIncrement=3 + +c3p0.checkoutTimeout=5000 +c3p0.maxIdleTime=7200 +c3p0.idleConnectionTestPeriod=18000 +#c3p0.maxIdleTimeExcessConnections=1800 + +#c3p0.automaticTestTable=C3P0TestTable +#c3p0.testConnectionOnCheckout=false +#c3p0.testConnectionOnCheckin=false + +#org.hibernate.dialect.MySQLInnoDBDialect +hibernate.dialect=org.hibernate.dialect.MySQLDialect +hibernate.show_sql=false +hibernate.format_sql=true +hibernate.hbm2ddl.auto=false +hibernate.jdbc.batch_size=50 +hibernate.query.substitutions=true 1,false 0 +hibernate.cache.use_second_level_cache=false +hibernate.cache.use_query_cache=false +hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory \ No newline at end of file diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml new file mode 100644 index 0000000..9b6a574 --- /dev/null +++ b/src/main/resources/logback.xml @@ -0,0 +1,37 @@ + + + + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger{50} %msg%n + + + + + + ${LOG_HOME}/quartzPro/localhost.log + + ${LOG_HOME}/quartzPro/%d{yyyy-MM-dd}.log + 30 + + 100MB + + + + %d{yyyy-MM-dd HH:mm:ss} 【%-5level】 【%logger{50}】 %msg%n + UTF-8 + + + WARN + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/quartz.xml b/src/main/resources/quartz.xml new file mode 100644 index 0000000..83e47c3 --- /dev/null +++ b/src/main/resources/quartz.xml @@ -0,0 +1,85 @@ + + + + + + + + + + + + + true + + + + + + + + + + + + + 0 0 10 * * ? + + + + + + + + + + + pushRemind + + + + + + + + + + + + + + + + + ${jpush.ios.appKey} + + + + ${jpush.ios.secret} + + + + ${jpush.ios.productionMode} + + + + + + + ${netease.appKey} + + + + ${netease.appSecret} + + + \ No newline at end of file diff --git a/src/main/webapp/META-INF/MANIFEST.MF b/src/main/webapp/META-INF/MANIFEST.MF new file mode 100644 index 0000000..254272e --- /dev/null +++ b/src/main/webapp/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Class-Path: + diff --git a/src/main/webapp/META-INF/context.xml b/src/main/webapp/META-INF/context.xml new file mode 100644 index 0000000..faf546b --- /dev/null +++ b/src/main/webapp/META-INF/context.xml @@ -0,0 +1,2 @@ + + diff --git a/src/main/webapp/WEB-INF/lib/mysql-connector-5.1.8.jar b/src/main/webapp/WEB-INF/lib/mysql-connector-5.1.8.jar new file mode 100644 index 0000000..5a7c6fb Binary files /dev/null and b/src/main/webapp/WEB-INF/lib/mysql-connector-5.1.8.jar differ diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000..4a43aef --- /dev/null +++ b/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,17 @@ + + + Archetype Created Web Application + + index.jsp + + + contextConfigLocation + + classpath:quartz.xml + + + + org.springframework.web.context.ContextLoaderListener + + + \ No newline at end of file diff --git a/src/main/webapp/index.jsp b/src/main/webapp/index.jsp new file mode 100644 index 0000000..2560447 --- /dev/null +++ b/src/main/webapp/index.jsp @@ -0,0 +1,11 @@ +<%@ page language="java" pageEncoding="utf-8"%> + + + + 首页 + + + +

    访问正常

    + + diff --git a/target/classes/.netbeans_automatic_build b/target/classes/.netbeans_automatic_build new file mode 100644 index 0000000..e69de29 diff --git a/target/classes/com/ifish/enums/NeteaseEnum.class b/target/classes/com/ifish/enums/NeteaseEnum.class new file mode 100644 index 0000000..8c3197e Binary files /dev/null and b/target/classes/com/ifish/enums/NeteaseEnum.class differ diff --git a/target/classes/com/ifish/enums/PhoneTypeEnum.class b/target/classes/com/ifish/enums/PhoneTypeEnum.class new file mode 100644 index 0000000..96bc0b8 Binary files /dev/null and b/target/classes/com/ifish/enums/PhoneTypeEnum.class differ diff --git a/target/classes/com/ifish/enums/PushTypeEnum.class b/target/classes/com/ifish/enums/PushTypeEnum.class new file mode 100644 index 0000000..7912063 Binary files /dev/null and b/target/classes/com/ifish/enums/PushTypeEnum.class differ diff --git a/target/classes/com/ifish/job/job.class b/target/classes/com/ifish/job/job.class new file mode 100644 index 0000000..af55b51 Binary files /dev/null and b/target/classes/com/ifish/job/job.class differ diff --git a/target/classes/com/ifish/jpush/JPushClient.class b/target/classes/com/ifish/jpush/JPushClient.class new file mode 100644 index 0000000..2f6e05c Binary files /dev/null and b/target/classes/com/ifish/jpush/JPushClient.class differ diff --git a/target/classes/com/ifish/jpush/JPushNotification.class b/target/classes/com/ifish/jpush/JPushNotification.class new file mode 100644 index 0000000..e4118a3 Binary files /dev/null and b/target/classes/com/ifish/jpush/JPushNotification.class differ diff --git a/target/classes/com/ifish/jpush/common/ClientConfig.class b/target/classes/com/ifish/jpush/common/ClientConfig.class new file mode 100644 index 0000000..926ab68 Binary files /dev/null and b/target/classes/com/ifish/jpush/common/ClientConfig.class differ diff --git a/target/classes/com/ifish/jpush/common/DeviceType.class b/target/classes/com/ifish/jpush/common/DeviceType.class new file mode 100644 index 0000000..46607fa Binary files /dev/null and b/target/classes/com/ifish/jpush/common/DeviceType.class differ diff --git a/target/classes/com/ifish/jpush/common/ServiceHelper.class b/target/classes/com/ifish/jpush/common/ServiceHelper.class new file mode 100644 index 0000000..c425eb0 Binary files /dev/null and b/target/classes/com/ifish/jpush/common/ServiceHelper.class differ diff --git a/target/classes/com/ifish/jpush/common/TimeUnit.class b/target/classes/com/ifish/jpush/common/TimeUnit.class new file mode 100644 index 0000000..cfb3f67 Binary files /dev/null and b/target/classes/com/ifish/jpush/common/TimeUnit.class differ diff --git a/target/classes/com/ifish/jpush/common/Week.class b/target/classes/com/ifish/jpush/common/Week.class new file mode 100644 index 0000000..18592b9 Binary files /dev/null and b/target/classes/com/ifish/jpush/common/Week.class differ diff --git a/target/classes/com/ifish/jpush/common/connection/HttpProxy.class b/target/classes/com/ifish/jpush/common/connection/HttpProxy.class new file mode 100644 index 0000000..5d77bb1 Binary files /dev/null and b/target/classes/com/ifish/jpush/common/connection/HttpProxy.class differ diff --git a/target/classes/com/ifish/jpush/common/connection/IHttpClient$RequestMethod.class b/target/classes/com/ifish/jpush/common/connection/IHttpClient$RequestMethod.class new file mode 100644 index 0000000..e31635f Binary files /dev/null and b/target/classes/com/ifish/jpush/common/connection/IHttpClient$RequestMethod.class differ diff --git a/target/classes/com/ifish/jpush/common/connection/IHttpClient.class b/target/classes/com/ifish/jpush/common/connection/IHttpClient.class new file mode 100644 index 0000000..1537b70 Binary files /dev/null and b/target/classes/com/ifish/jpush/common/connection/IHttpClient.class differ diff --git a/target/classes/com/ifish/jpush/common/connection/NativeHttpClient$1.class b/target/classes/com/ifish/jpush/common/connection/NativeHttpClient$1.class new file mode 100644 index 0000000..9011f78 Binary files /dev/null and b/target/classes/com/ifish/jpush/common/connection/NativeHttpClient$1.class differ diff --git a/target/classes/com/ifish/jpush/common/connection/NativeHttpClient$2.class b/target/classes/com/ifish/jpush/common/connection/NativeHttpClient$2.class new file mode 100644 index 0000000..89bfa8f Binary files /dev/null and b/target/classes/com/ifish/jpush/common/connection/NativeHttpClient$2.class differ diff --git a/target/classes/com/ifish/jpush/common/connection/NativeHttpClient$SimpleHostnameVerifier.class b/target/classes/com/ifish/jpush/common/connection/NativeHttpClient$SimpleHostnameVerifier.class new file mode 100644 index 0000000..d04a61c Binary files /dev/null and b/target/classes/com/ifish/jpush/common/connection/NativeHttpClient$SimpleHostnameVerifier.class differ diff --git a/target/classes/com/ifish/jpush/common/connection/NativeHttpClient$SimpleProxyAuthenticator.class b/target/classes/com/ifish/jpush/common/connection/NativeHttpClient$SimpleProxyAuthenticator.class new file mode 100644 index 0000000..5b0f8e1 Binary files /dev/null and b/target/classes/com/ifish/jpush/common/connection/NativeHttpClient$SimpleProxyAuthenticator.class differ diff --git a/target/classes/com/ifish/jpush/common/connection/NativeHttpClient$SimpleTrustManager.class b/target/classes/com/ifish/jpush/common/connection/NativeHttpClient$SimpleTrustManager.class new file mode 100644 index 0000000..51b94f3 Binary files /dev/null and b/target/classes/com/ifish/jpush/common/connection/NativeHttpClient$SimpleTrustManager.class differ diff --git a/target/classes/com/ifish/jpush/common/connection/NativeHttpClient.class b/target/classes/com/ifish/jpush/common/connection/NativeHttpClient.class new file mode 100644 index 0000000..b6c1264 Binary files /dev/null and b/target/classes/com/ifish/jpush/common/connection/NativeHttpClient.class differ diff --git a/target/classes/com/ifish/jpush/common/resp/APIConnectionException.class b/target/classes/com/ifish/jpush/common/resp/APIConnectionException.class new file mode 100644 index 0000000..0aef24d Binary files /dev/null and b/target/classes/com/ifish/jpush/common/resp/APIConnectionException.class differ diff --git a/target/classes/com/ifish/jpush/common/resp/APIRequestException.class b/target/classes/com/ifish/jpush/common/resp/APIRequestException.class new file mode 100644 index 0000000..87e66ba Binary files /dev/null and b/target/classes/com/ifish/jpush/common/resp/APIRequestException.class differ diff --git a/target/classes/com/ifish/jpush/common/resp/BaseResult.class b/target/classes/com/ifish/jpush/common/resp/BaseResult.class new file mode 100644 index 0000000..001991d Binary files /dev/null and b/target/classes/com/ifish/jpush/common/resp/BaseResult.class differ diff --git a/target/classes/com/ifish/jpush/common/resp/BooleanResult.class b/target/classes/com/ifish/jpush/common/resp/BooleanResult.class new file mode 100644 index 0000000..40876c5 Binary files /dev/null and b/target/classes/com/ifish/jpush/common/resp/BooleanResult.class differ diff --git a/target/classes/com/ifish/jpush/common/resp/DefaultResult.class b/target/classes/com/ifish/jpush/common/resp/DefaultResult.class new file mode 100644 index 0000000..86e433d Binary files /dev/null and b/target/classes/com/ifish/jpush/common/resp/DefaultResult.class differ diff --git a/target/classes/com/ifish/jpush/common/resp/IRateLimiting.class b/target/classes/com/ifish/jpush/common/resp/IRateLimiting.class new file mode 100644 index 0000000..cd5841f Binary files /dev/null and b/target/classes/com/ifish/jpush/common/resp/IRateLimiting.class differ diff --git a/target/classes/com/ifish/jpush/common/resp/ResponseWrapper$ErrorEntity.class b/target/classes/com/ifish/jpush/common/resp/ResponseWrapper$ErrorEntity.class new file mode 100644 index 0000000..434f573 Binary files /dev/null and b/target/classes/com/ifish/jpush/common/resp/ResponseWrapper$ErrorEntity.class differ diff --git a/target/classes/com/ifish/jpush/common/resp/ResponseWrapper$ErrorObject.class b/target/classes/com/ifish/jpush/common/resp/ResponseWrapper$ErrorObject.class new file mode 100644 index 0000000..d37fadc Binary files /dev/null and b/target/classes/com/ifish/jpush/common/resp/ResponseWrapper$ErrorObject.class differ diff --git a/target/classes/com/ifish/jpush/common/resp/ResponseWrapper.class b/target/classes/com/ifish/jpush/common/resp/ResponseWrapper.class new file mode 100644 index 0000000..489843b Binary files /dev/null and b/target/classes/com/ifish/jpush/common/resp/ResponseWrapper.class differ diff --git a/target/classes/com/ifish/jpush/device/AliasDeviceListResult.class b/target/classes/com/ifish/jpush/device/AliasDeviceListResult.class new file mode 100644 index 0000000..edaae48 Binary files /dev/null and b/target/classes/com/ifish/jpush/device/AliasDeviceListResult.class differ diff --git a/target/classes/com/ifish/jpush/device/DeviceClient$1.class b/target/classes/com/ifish/jpush/device/DeviceClient$1.class new file mode 100644 index 0000000..6c0e444 Binary files /dev/null and b/target/classes/com/ifish/jpush/device/DeviceClient$1.class differ diff --git a/target/classes/com/ifish/jpush/device/DeviceClient.class b/target/classes/com/ifish/jpush/device/DeviceClient.class new file mode 100644 index 0000000..5508473 Binary files /dev/null and b/target/classes/com/ifish/jpush/device/DeviceClient.class differ diff --git a/target/classes/com/ifish/jpush/device/OnlineStatus.class b/target/classes/com/ifish/jpush/device/OnlineStatus.class new file mode 100644 index 0000000..4f2d305 Binary files /dev/null and b/target/classes/com/ifish/jpush/device/OnlineStatus.class differ diff --git a/target/classes/com/ifish/jpush/device/TagAliasResult.class b/target/classes/com/ifish/jpush/device/TagAliasResult.class new file mode 100644 index 0000000..9f21849 Binary files /dev/null and b/target/classes/com/ifish/jpush/device/TagAliasResult.class differ diff --git a/target/classes/com/ifish/jpush/device/TagListResult.class b/target/classes/com/ifish/jpush/device/TagListResult.class new file mode 100644 index 0000000..6491697 Binary files /dev/null and b/target/classes/com/ifish/jpush/device/TagListResult.class differ diff --git a/target/classes/com/ifish/jpush/examples/DevcieExample.class b/target/classes/com/ifish/jpush/examples/DevcieExample.class new file mode 100644 index 0000000..15feffc Binary files /dev/null and b/target/classes/com/ifish/jpush/examples/DevcieExample.class differ diff --git a/target/classes/com/ifish/jpush/examples/PushExample.class b/target/classes/com/ifish/jpush/examples/PushExample.class new file mode 100644 index 0000000..167e26c Binary files /dev/null and b/target/classes/com/ifish/jpush/examples/PushExample.class differ diff --git a/target/classes/com/ifish/jpush/examples/ReportsExample.class b/target/classes/com/ifish/jpush/examples/ReportsExample.class new file mode 100644 index 0000000..87fc25a Binary files /dev/null and b/target/classes/com/ifish/jpush/examples/ReportsExample.class differ diff --git a/target/classes/com/ifish/jpush/examples/ScheduleExample.class b/target/classes/com/ifish/jpush/examples/ScheduleExample.class new file mode 100644 index 0000000..5ccf731 Binary files /dev/null and b/target/classes/com/ifish/jpush/examples/ScheduleExample.class differ diff --git a/target/classes/com/ifish/jpush/push/PushClient.class b/target/classes/com/ifish/jpush/push/PushClient.class new file mode 100644 index 0000000..61ccc96 Binary files /dev/null and b/target/classes/com/ifish/jpush/push/PushClient.class differ diff --git a/target/classes/com/ifish/jpush/push/PushResult.class b/target/classes/com/ifish/jpush/push/PushResult.class new file mode 100644 index 0000000..5ad297a Binary files /dev/null and b/target/classes/com/ifish/jpush/push/PushResult.class differ diff --git a/target/classes/com/ifish/jpush/push/model/Message$1.class b/target/classes/com/ifish/jpush/push/model/Message$1.class new file mode 100644 index 0000000..045535f Binary files /dev/null and b/target/classes/com/ifish/jpush/push/model/Message$1.class differ diff --git a/target/classes/com/ifish/jpush/push/model/Message$Builder.class b/target/classes/com/ifish/jpush/push/model/Message$Builder.class new file mode 100644 index 0000000..a3864d6 Binary files /dev/null and b/target/classes/com/ifish/jpush/push/model/Message$Builder.class differ diff --git a/target/classes/com/ifish/jpush/push/model/Message.class b/target/classes/com/ifish/jpush/push/model/Message.class new file mode 100644 index 0000000..9f13e44 Binary files /dev/null and b/target/classes/com/ifish/jpush/push/model/Message.class differ diff --git a/target/classes/com/ifish/jpush/push/model/Options$1.class b/target/classes/com/ifish/jpush/push/model/Options$1.class new file mode 100644 index 0000000..81ec651 Binary files /dev/null and b/target/classes/com/ifish/jpush/push/model/Options$1.class differ diff --git a/target/classes/com/ifish/jpush/push/model/Options$Builder.class b/target/classes/com/ifish/jpush/push/model/Options$Builder.class new file mode 100644 index 0000000..e3d5394 Binary files /dev/null and b/target/classes/com/ifish/jpush/push/model/Options$Builder.class differ diff --git a/target/classes/com/ifish/jpush/push/model/Options.class b/target/classes/com/ifish/jpush/push/model/Options.class new file mode 100644 index 0000000..bc0af9a Binary files /dev/null and b/target/classes/com/ifish/jpush/push/model/Options.class differ diff --git a/target/classes/com/ifish/jpush/push/model/Platform$1.class b/target/classes/com/ifish/jpush/push/model/Platform$1.class new file mode 100644 index 0000000..32cca0f Binary files /dev/null and b/target/classes/com/ifish/jpush/push/model/Platform$1.class differ diff --git a/target/classes/com/ifish/jpush/push/model/Platform$Builder.class b/target/classes/com/ifish/jpush/push/model/Platform$Builder.class new file mode 100644 index 0000000..1337186 Binary files /dev/null and b/target/classes/com/ifish/jpush/push/model/Platform$Builder.class differ diff --git a/target/classes/com/ifish/jpush/push/model/Platform.class b/target/classes/com/ifish/jpush/push/model/Platform.class new file mode 100644 index 0000000..21eefc3 Binary files /dev/null and b/target/classes/com/ifish/jpush/push/model/Platform.class differ diff --git a/target/classes/com/ifish/jpush/push/model/PushModel.class b/target/classes/com/ifish/jpush/push/model/PushModel.class new file mode 100644 index 0000000..1a5aad3 Binary files /dev/null and b/target/classes/com/ifish/jpush/push/model/PushModel.class differ diff --git a/target/classes/com/ifish/jpush/push/model/PushPayload$1.class b/target/classes/com/ifish/jpush/push/model/PushPayload$1.class new file mode 100644 index 0000000..a0e8e26 Binary files /dev/null and b/target/classes/com/ifish/jpush/push/model/PushPayload$1.class differ diff --git a/target/classes/com/ifish/jpush/push/model/PushPayload$Builder.class b/target/classes/com/ifish/jpush/push/model/PushPayload$Builder.class new file mode 100644 index 0000000..bb95713 Binary files /dev/null and b/target/classes/com/ifish/jpush/push/model/PushPayload$Builder.class differ diff --git a/target/classes/com/ifish/jpush/push/model/PushPayload.class b/target/classes/com/ifish/jpush/push/model/PushPayload.class new file mode 100644 index 0000000..b6914ac Binary files /dev/null and b/target/classes/com/ifish/jpush/push/model/PushPayload.class differ diff --git a/target/classes/com/ifish/jpush/push/model/audience/Audience$1.class b/target/classes/com/ifish/jpush/push/model/audience/Audience$1.class new file mode 100644 index 0000000..6c9998b Binary files /dev/null and b/target/classes/com/ifish/jpush/push/model/audience/Audience$1.class differ diff --git a/target/classes/com/ifish/jpush/push/model/audience/Audience$Builder.class b/target/classes/com/ifish/jpush/push/model/audience/Audience$Builder.class new file mode 100644 index 0000000..f742942 Binary files /dev/null and b/target/classes/com/ifish/jpush/push/model/audience/Audience$Builder.class differ diff --git a/target/classes/com/ifish/jpush/push/model/audience/Audience.class b/target/classes/com/ifish/jpush/push/model/audience/Audience.class new file mode 100644 index 0000000..a3619c8 Binary files /dev/null and b/target/classes/com/ifish/jpush/push/model/audience/Audience.class differ diff --git a/target/classes/com/ifish/jpush/push/model/audience/AudienceTarget$1.class b/target/classes/com/ifish/jpush/push/model/audience/AudienceTarget$1.class new file mode 100644 index 0000000..bf4a7b0 Binary files /dev/null and b/target/classes/com/ifish/jpush/push/model/audience/AudienceTarget$1.class differ diff --git a/target/classes/com/ifish/jpush/push/model/audience/AudienceTarget$Builder.class b/target/classes/com/ifish/jpush/push/model/audience/AudienceTarget$Builder.class new file mode 100644 index 0000000..b2b84f6 Binary files /dev/null and b/target/classes/com/ifish/jpush/push/model/audience/AudienceTarget$Builder.class differ diff --git a/target/classes/com/ifish/jpush/push/model/audience/AudienceTarget.class b/target/classes/com/ifish/jpush/push/model/audience/AudienceTarget.class new file mode 100644 index 0000000..2b18df0 Binary files /dev/null and b/target/classes/com/ifish/jpush/push/model/audience/AudienceTarget.class differ diff --git a/target/classes/com/ifish/jpush/push/model/audience/AudienceType.class b/target/classes/com/ifish/jpush/push/model/audience/AudienceType.class new file mode 100644 index 0000000..7be5de0 Binary files /dev/null and b/target/classes/com/ifish/jpush/push/model/audience/AudienceType.class differ diff --git a/target/classes/com/ifish/jpush/push/model/notification/AndroidNotification$1.class b/target/classes/com/ifish/jpush/push/model/notification/AndroidNotification$1.class new file mode 100644 index 0000000..c0c0031 Binary files /dev/null and b/target/classes/com/ifish/jpush/push/model/notification/AndroidNotification$1.class differ diff --git a/target/classes/com/ifish/jpush/push/model/notification/AndroidNotification$Builder.class b/target/classes/com/ifish/jpush/push/model/notification/AndroidNotification$Builder.class new file mode 100644 index 0000000..e155188 Binary files /dev/null and b/target/classes/com/ifish/jpush/push/model/notification/AndroidNotification$Builder.class differ diff --git a/target/classes/com/ifish/jpush/push/model/notification/AndroidNotification.class b/target/classes/com/ifish/jpush/push/model/notification/AndroidNotification.class new file mode 100644 index 0000000..28d9e15 Binary files /dev/null and b/target/classes/com/ifish/jpush/push/model/notification/AndroidNotification.class differ diff --git a/target/classes/com/ifish/jpush/push/model/notification/IosAlert$1.class b/target/classes/com/ifish/jpush/push/model/notification/IosAlert$1.class new file mode 100644 index 0000000..296c21e Binary files /dev/null and b/target/classes/com/ifish/jpush/push/model/notification/IosAlert$1.class differ diff --git a/target/classes/com/ifish/jpush/push/model/notification/IosAlert$Builder.class b/target/classes/com/ifish/jpush/push/model/notification/IosAlert$Builder.class new file mode 100644 index 0000000..32f258e Binary files /dev/null and b/target/classes/com/ifish/jpush/push/model/notification/IosAlert$Builder.class differ diff --git a/target/classes/com/ifish/jpush/push/model/notification/IosAlert.class b/target/classes/com/ifish/jpush/push/model/notification/IosAlert.class new file mode 100644 index 0000000..09bcae6 Binary files /dev/null and b/target/classes/com/ifish/jpush/push/model/notification/IosAlert.class differ diff --git a/target/classes/com/ifish/jpush/push/model/notification/IosNotification$1.class b/target/classes/com/ifish/jpush/push/model/notification/IosNotification$1.class new file mode 100644 index 0000000..cadaf11 Binary files /dev/null and b/target/classes/com/ifish/jpush/push/model/notification/IosNotification$1.class differ diff --git a/target/classes/com/ifish/jpush/push/model/notification/IosNotification$Builder.class b/target/classes/com/ifish/jpush/push/model/notification/IosNotification$Builder.class new file mode 100644 index 0000000..68b3f35 Binary files /dev/null and b/target/classes/com/ifish/jpush/push/model/notification/IosNotification$Builder.class differ diff --git a/target/classes/com/ifish/jpush/push/model/notification/IosNotification.class b/target/classes/com/ifish/jpush/push/model/notification/IosNotification.class new file mode 100644 index 0000000..83eaf97 Binary files /dev/null and b/target/classes/com/ifish/jpush/push/model/notification/IosNotification.class differ diff --git a/target/classes/com/ifish/jpush/push/model/notification/Notification$1.class b/target/classes/com/ifish/jpush/push/model/notification/Notification$1.class new file mode 100644 index 0000000..349c10f Binary files /dev/null and b/target/classes/com/ifish/jpush/push/model/notification/Notification$1.class differ diff --git a/target/classes/com/ifish/jpush/push/model/notification/Notification$Builder.class b/target/classes/com/ifish/jpush/push/model/notification/Notification$Builder.class new file mode 100644 index 0000000..c9767e6 Binary files /dev/null and b/target/classes/com/ifish/jpush/push/model/notification/Notification$Builder.class differ diff --git a/target/classes/com/ifish/jpush/push/model/notification/Notification.class b/target/classes/com/ifish/jpush/push/model/notification/Notification.class new file mode 100644 index 0000000..ec199cd Binary files /dev/null and b/target/classes/com/ifish/jpush/push/model/notification/Notification.class differ diff --git a/target/classes/com/ifish/jpush/push/model/notification/PlatformNotification$Builder.class b/target/classes/com/ifish/jpush/push/model/notification/PlatformNotification$Builder.class new file mode 100644 index 0000000..41a9970 Binary files /dev/null and b/target/classes/com/ifish/jpush/push/model/notification/PlatformNotification$Builder.class differ diff --git a/target/classes/com/ifish/jpush/push/model/notification/PlatformNotification.class b/target/classes/com/ifish/jpush/push/model/notification/PlatformNotification.class new file mode 100644 index 0000000..28322bb Binary files /dev/null and b/target/classes/com/ifish/jpush/push/model/notification/PlatformNotification.class differ diff --git a/target/classes/com/ifish/jpush/push/model/notification/WinphoneNotification$1.class b/target/classes/com/ifish/jpush/push/model/notification/WinphoneNotification$1.class new file mode 100644 index 0000000..cd13a9e Binary files /dev/null and b/target/classes/com/ifish/jpush/push/model/notification/WinphoneNotification$1.class differ diff --git a/target/classes/com/ifish/jpush/push/model/notification/WinphoneNotification$Builder.class b/target/classes/com/ifish/jpush/push/model/notification/WinphoneNotification$Builder.class new file mode 100644 index 0000000..88d31a3 Binary files /dev/null and b/target/classes/com/ifish/jpush/push/model/notification/WinphoneNotification$Builder.class differ diff --git a/target/classes/com/ifish/jpush/push/model/notification/WinphoneNotification.class b/target/classes/com/ifish/jpush/push/model/notification/WinphoneNotification.class new file mode 100644 index 0000000..965ffb3 Binary files /dev/null and b/target/classes/com/ifish/jpush/push/model/notification/WinphoneNotification.class differ diff --git a/target/classes/com/ifish/jpush/report/MessagesResult$1.class b/target/classes/com/ifish/jpush/report/MessagesResult$1.class new file mode 100644 index 0000000..e432bda Binary files /dev/null and b/target/classes/com/ifish/jpush/report/MessagesResult$1.class differ diff --git a/target/classes/com/ifish/jpush/report/MessagesResult$Android.class b/target/classes/com/ifish/jpush/report/MessagesResult$Android.class new file mode 100644 index 0000000..96a7eab Binary files /dev/null and b/target/classes/com/ifish/jpush/report/MessagesResult$Android.class differ diff --git a/target/classes/com/ifish/jpush/report/MessagesResult$Ios.class b/target/classes/com/ifish/jpush/report/MessagesResult$Ios.class new file mode 100644 index 0000000..d44350f Binary files /dev/null and b/target/classes/com/ifish/jpush/report/MessagesResult$Ios.class differ diff --git a/target/classes/com/ifish/jpush/report/MessagesResult$Message.class b/target/classes/com/ifish/jpush/report/MessagesResult$Message.class new file mode 100644 index 0000000..2469e32 Binary files /dev/null and b/target/classes/com/ifish/jpush/report/MessagesResult$Message.class differ diff --git a/target/classes/com/ifish/jpush/report/MessagesResult.class b/target/classes/com/ifish/jpush/report/MessagesResult.class new file mode 100644 index 0000000..51a4059 Binary files /dev/null and b/target/classes/com/ifish/jpush/report/MessagesResult.class differ diff --git a/target/classes/com/ifish/jpush/report/ReceivedsResult$1.class b/target/classes/com/ifish/jpush/report/ReceivedsResult$1.class new file mode 100644 index 0000000..b42148f Binary files /dev/null and b/target/classes/com/ifish/jpush/report/ReceivedsResult$1.class differ diff --git a/target/classes/com/ifish/jpush/report/ReceivedsResult$Received.class b/target/classes/com/ifish/jpush/report/ReceivedsResult$Received.class new file mode 100644 index 0000000..962f0fe Binary files /dev/null and b/target/classes/com/ifish/jpush/report/ReceivedsResult$Received.class differ diff --git a/target/classes/com/ifish/jpush/report/ReceivedsResult.class b/target/classes/com/ifish/jpush/report/ReceivedsResult.class new file mode 100644 index 0000000..17ea12c Binary files /dev/null and b/target/classes/com/ifish/jpush/report/ReceivedsResult.class differ diff --git a/target/classes/com/ifish/jpush/report/ReportClient.class b/target/classes/com/ifish/jpush/report/ReportClient.class new file mode 100644 index 0000000..2e19042 Binary files /dev/null and b/target/classes/com/ifish/jpush/report/ReportClient.class differ diff --git a/target/classes/com/ifish/jpush/report/UsersResult$Android.class b/target/classes/com/ifish/jpush/report/UsersResult$Android.class new file mode 100644 index 0000000..74b8b8e Binary files /dev/null and b/target/classes/com/ifish/jpush/report/UsersResult$Android.class differ diff --git a/target/classes/com/ifish/jpush/report/UsersResult$Ios.class b/target/classes/com/ifish/jpush/report/UsersResult$Ios.class new file mode 100644 index 0000000..f76a6e3 Binary files /dev/null and b/target/classes/com/ifish/jpush/report/UsersResult$Ios.class differ diff --git a/target/classes/com/ifish/jpush/report/UsersResult$User.class b/target/classes/com/ifish/jpush/report/UsersResult$User.class new file mode 100644 index 0000000..78e6702 Binary files /dev/null and b/target/classes/com/ifish/jpush/report/UsersResult$User.class differ diff --git a/target/classes/com/ifish/jpush/report/UsersResult.class b/target/classes/com/ifish/jpush/report/UsersResult.class new file mode 100644 index 0000000..b18ebb4 Binary files /dev/null and b/target/classes/com/ifish/jpush/report/UsersResult.class differ diff --git a/target/classes/com/ifish/jpush/schedule/ScheduleClient.class b/target/classes/com/ifish/jpush/schedule/ScheduleClient.class new file mode 100644 index 0000000..8863a54 Binary files /dev/null and b/target/classes/com/ifish/jpush/schedule/ScheduleClient.class differ diff --git a/target/classes/com/ifish/jpush/schedule/ScheduleListResult.class b/target/classes/com/ifish/jpush/schedule/ScheduleListResult.class new file mode 100644 index 0000000..9f10557 Binary files /dev/null and b/target/classes/com/ifish/jpush/schedule/ScheduleListResult.class differ diff --git a/target/classes/com/ifish/jpush/schedule/ScheduleResult.class b/target/classes/com/ifish/jpush/schedule/ScheduleResult.class new file mode 100644 index 0000000..278a7f0 Binary files /dev/null and b/target/classes/com/ifish/jpush/schedule/ScheduleResult.class differ diff --git a/target/classes/com/ifish/jpush/schedule/model/IModel.class b/target/classes/com/ifish/jpush/schedule/model/IModel.class new file mode 100644 index 0000000..38c82d1 Binary files /dev/null and b/target/classes/com/ifish/jpush/schedule/model/IModel.class differ diff --git a/target/classes/com/ifish/jpush/schedule/model/SchedulePayload$1.class b/target/classes/com/ifish/jpush/schedule/model/SchedulePayload$1.class new file mode 100644 index 0000000..6adfdde Binary files /dev/null and b/target/classes/com/ifish/jpush/schedule/model/SchedulePayload$1.class differ diff --git a/target/classes/com/ifish/jpush/schedule/model/SchedulePayload$Builder.class b/target/classes/com/ifish/jpush/schedule/model/SchedulePayload$Builder.class new file mode 100644 index 0000000..8739e19 Binary files /dev/null and b/target/classes/com/ifish/jpush/schedule/model/SchedulePayload$Builder.class differ diff --git a/target/classes/com/ifish/jpush/schedule/model/SchedulePayload.class b/target/classes/com/ifish/jpush/schedule/model/SchedulePayload.class new file mode 100644 index 0000000..3aa2461 Binary files /dev/null and b/target/classes/com/ifish/jpush/schedule/model/SchedulePayload.class differ diff --git a/target/classes/com/ifish/jpush/schedule/model/TriggerPayload$1.class b/target/classes/com/ifish/jpush/schedule/model/TriggerPayload$1.class new file mode 100644 index 0000000..a3995b8 Binary files /dev/null and b/target/classes/com/ifish/jpush/schedule/model/TriggerPayload$1.class differ diff --git a/target/classes/com/ifish/jpush/schedule/model/TriggerPayload$2.class b/target/classes/com/ifish/jpush/schedule/model/TriggerPayload$2.class new file mode 100644 index 0000000..d232cf8 Binary files /dev/null and b/target/classes/com/ifish/jpush/schedule/model/TriggerPayload$2.class differ diff --git a/target/classes/com/ifish/jpush/schedule/model/TriggerPayload$3.class b/target/classes/com/ifish/jpush/schedule/model/TriggerPayload$3.class new file mode 100644 index 0000000..f1feae6 Binary files /dev/null and b/target/classes/com/ifish/jpush/schedule/model/TriggerPayload$3.class differ diff --git a/target/classes/com/ifish/jpush/schedule/model/TriggerPayload$Builder.class b/target/classes/com/ifish/jpush/schedule/model/TriggerPayload$Builder.class new file mode 100644 index 0000000..e1e3301 Binary files /dev/null and b/target/classes/com/ifish/jpush/schedule/model/TriggerPayload$Builder.class differ diff --git a/target/classes/com/ifish/jpush/schedule/model/TriggerPayload$Type.class b/target/classes/com/ifish/jpush/schedule/model/TriggerPayload$Type.class new file mode 100644 index 0000000..0d5d704 Binary files /dev/null and b/target/classes/com/ifish/jpush/schedule/model/TriggerPayload$Type.class differ diff --git a/target/classes/com/ifish/jpush/schedule/model/TriggerPayload.class b/target/classes/com/ifish/jpush/schedule/model/TriggerPayload.class new file mode 100644 index 0000000..f2e2177 Binary files /dev/null and b/target/classes/com/ifish/jpush/schedule/model/TriggerPayload.class differ diff --git a/target/classes/com/ifish/jpush/utils/Base64.class b/target/classes/com/ifish/jpush/utils/Base64.class new file mode 100644 index 0000000..3bd6272 Binary files /dev/null and b/target/classes/com/ifish/jpush/utils/Base64.class differ diff --git a/target/classes/com/ifish/jpush/utils/Nullable.class b/target/classes/com/ifish/jpush/utils/Nullable.class new file mode 100644 index 0000000..aa02d22 Binary files /dev/null and b/target/classes/com/ifish/jpush/utils/Nullable.class differ diff --git a/target/classes/com/ifish/jpush/utils/Preconditions.class b/target/classes/com/ifish/jpush/utils/Preconditions.class new file mode 100644 index 0000000..d7dfb05 Binary files /dev/null and b/target/classes/com/ifish/jpush/utils/Preconditions.class differ diff --git a/target/classes/com/ifish/jpush/utils/StringUtils.class b/target/classes/com/ifish/jpush/utils/StringUtils.class new file mode 100644 index 0000000..231f926 Binary files /dev/null and b/target/classes/com/ifish/jpush/utils/StringUtils.class differ diff --git a/target/classes/com/ifish/jpush/utils/TimeUtils.class b/target/classes/com/ifish/jpush/utils/TimeUtils.class new file mode 100644 index 0000000..828ea04 Binary files /dev/null and b/target/classes/com/ifish/jpush/utils/TimeUtils.class differ diff --git a/target/classes/com/ifish/netease/CheckSumBuilder.class b/target/classes/com/ifish/netease/CheckSumBuilder.class new file mode 100644 index 0000000..6730b43 Binary files /dev/null and b/target/classes/com/ifish/netease/CheckSumBuilder.class differ diff --git a/target/classes/com/ifish/netease/NeteaseIM.class b/target/classes/com/ifish/netease/NeteaseIM.class new file mode 100644 index 0000000..6be7870 Binary files /dev/null and b/target/classes/com/ifish/netease/NeteaseIM.class differ diff --git a/target/classes/com/ifish/tianqi/javaDemo.class b/target/classes/com/ifish/tianqi/javaDemo.class new file mode 100644 index 0000000..9b03189 Binary files /dev/null and b/target/classes/com/ifish/tianqi/javaDemo.class differ diff --git a/target/classes/com/ifish/util/IfishUtil.class b/target/classes/com/ifish/util/IfishUtil.class new file mode 100644 index 0000000..1462a3f Binary files /dev/null and b/target/classes/com/ifish/util/IfishUtil.class differ diff --git a/target/classes/jPpush.properties b/target/classes/jPpush.properties new file mode 100644 index 0000000..4c46f36 --- /dev/null +++ b/target/classes/jPpush.properties @@ -0,0 +1,16 @@ +#极光推送 +#appKey +jpush.android.appKey=d970d5e193cb2a0bbe41653c +#secret +jpush.android.secret=60162c8cf195ce9f4dc76629 +#production +jpush.android.productionMode=true +#appKey +jpush.ios.appKey=d147124018074eb970474e48 +#secret +jpush.ios.secret=a7d41825e75082b13675c326 +#production +jpush.ios.productionMode=true +#云信IM +netease.appKey=87b0e3315dfc2df08060bcb54246da68 +netease.appSecret=e62f6c247b46 diff --git a/target/classes/jdbc.properties b/target/classes/jdbc.properties new file mode 100644 index 0000000..f20d58c --- /dev/null +++ b/target/classes/jdbc.properties @@ -0,0 +1,32 @@ +c3p0.driverClassName=com.mysql.jdbc.Driver +c3p0.url=jdbc\:mysql\://localhost\:3306/myfishdb?characterEncoding\=UTF-8 +c3p0.username=ifish +c3p0.password=ifish7pwd +#c3p0.username=root +#c3p0.password=123456 + +c3p0.autoCommitOnClose=true +c3p0.initialPoolSize=50 +c3p0.minPoolSize=50 +c3p0.maxPoolSize=100 +c3p0.acquireIncrement=3 + +c3p0.checkoutTimeout=5000 +c3p0.maxIdleTime=7200 +c3p0.idleConnectionTestPeriod=18000 +#c3p0.maxIdleTimeExcessConnections=1800 + +#c3p0.automaticTestTable=C3P0TestTable +#c3p0.testConnectionOnCheckout=false +#c3p0.testConnectionOnCheckin=false + +#org.hibernate.dialect.MySQLInnoDBDialect +hibernate.dialect=org.hibernate.dialect.MySQLDialect +hibernate.show_sql=false +hibernate.format_sql=true +hibernate.hbm2ddl.auto=false +hibernate.jdbc.batch_size=50 +hibernate.query.substitutions=true 1,false 0 +hibernate.cache.use_second_level_cache=false +hibernate.cache.use_query_cache=false +hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory \ No newline at end of file diff --git a/target/classes/logback.xml b/target/classes/logback.xml new file mode 100644 index 0000000..9b6a574 --- /dev/null +++ b/target/classes/logback.xml @@ -0,0 +1,37 @@ + + + + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger{50} %msg%n + + + + + + ${LOG_HOME}/quartzPro/localhost.log + + ${LOG_HOME}/quartzPro/%d{yyyy-MM-dd}.log + 30 + + 100MB + + + + %d{yyyy-MM-dd HH:mm:ss} 【%-5level】 【%logger{50}】 %msg%n + UTF-8 + + + WARN + + + + + + + + + + + \ No newline at end of file diff --git a/target/classes/quartz.xml b/target/classes/quartz.xml new file mode 100644 index 0000000..83e47c3 --- /dev/null +++ b/target/classes/quartz.xml @@ -0,0 +1,85 @@ + + + + + + + + + + + + + true + + + + + + + + + + + + + 0 0 10 * * ? + + + + + + + + + + + pushRemind + + + + + + + + + + + + + + + + + ${jpush.ios.appKey} + + + + ${jpush.ios.secret} + + + + ${jpush.ios.productionMode} + + + + + + + ${netease.appKey} + + + + ${netease.appSecret} + + + \ No newline at end of file diff --git a/target/maven-archiver/pom.properties b/target/maven-archiver/pom.properties new file mode 100644 index 0000000..f1d6399 --- /dev/null +++ b/target/maven-archiver/pom.properties @@ -0,0 +1,5 @@ +#Generated by Maven +#Mon Aug 07 09:29:12 CST 2017 +version=0.0.1-SNAPSHOT +groupId=quartzPro +artifactId=quartzPro diff --git a/target/quartzPro.war b/target/quartzPro.war new file mode 100644 index 0000000..57028f9 Binary files /dev/null and b/target/quartzPro.war differ diff --git a/target/quartzPro/META-INF/MANIFEST.MF b/target/quartzPro/META-INF/MANIFEST.MF new file mode 100644 index 0000000..254272e --- /dev/null +++ b/target/quartzPro/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Class-Path: + diff --git a/target/quartzPro/META-INF/context.xml b/target/quartzPro/META-INF/context.xml new file mode 100644 index 0000000..faf546b --- /dev/null +++ b/target/quartzPro/META-INF/context.xml @@ -0,0 +1,2 @@ + + diff --git a/target/quartzPro/WEB-INF/classes/.netbeans_automatic_build b/target/quartzPro/WEB-INF/classes/.netbeans_automatic_build new file mode 100644 index 0000000..e69de29 diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/enums/NeteaseEnum.class b/target/quartzPro/WEB-INF/classes/com/ifish/enums/NeteaseEnum.class new file mode 100644 index 0000000..8c3197e Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/enums/NeteaseEnum.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/enums/PhoneTypeEnum.class b/target/quartzPro/WEB-INF/classes/com/ifish/enums/PhoneTypeEnum.class new file mode 100644 index 0000000..96bc0b8 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/enums/PhoneTypeEnum.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/enums/PushTypeEnum.class b/target/quartzPro/WEB-INF/classes/com/ifish/enums/PushTypeEnum.class new file mode 100644 index 0000000..7912063 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/enums/PushTypeEnum.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/job/job.class b/target/quartzPro/WEB-INF/classes/com/ifish/job/job.class new file mode 100644 index 0000000..a3c8cc9 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/job/job.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/JPushClient.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/JPushClient.class new file mode 100644 index 0000000..a621fed Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/JPushClient.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/JPushNotification.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/JPushNotification.class new file mode 100644 index 0000000..005f725 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/JPushNotification.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/ClientConfig.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/ClientConfig.class new file mode 100644 index 0000000..926ab68 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/ClientConfig.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/DeviceType.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/DeviceType.class new file mode 100644 index 0000000..46607fa Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/DeviceType.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/ServiceHelper.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/ServiceHelper.class new file mode 100644 index 0000000..a0d6fc9 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/ServiceHelper.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/TimeUnit.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/TimeUnit.class new file mode 100644 index 0000000..cfb3f67 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/TimeUnit.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/Week.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/Week.class new file mode 100644 index 0000000..18592b9 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/Week.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/connection/HttpProxy.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/connection/HttpProxy.class new file mode 100644 index 0000000..f1de66d Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/connection/HttpProxy.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/connection/IHttpClient$RequestMethod.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/connection/IHttpClient$RequestMethod.class new file mode 100644 index 0000000..e31635f Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/connection/IHttpClient$RequestMethod.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/connection/IHttpClient.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/connection/IHttpClient.class new file mode 100644 index 0000000..0c9ac3d Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/connection/IHttpClient.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/connection/NativeHttpClient$1.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/connection/NativeHttpClient$1.class new file mode 100644 index 0000000..9011f78 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/connection/NativeHttpClient$1.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/connection/NativeHttpClient$SimpleHostnameVerifier.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/connection/NativeHttpClient$SimpleHostnameVerifier.class new file mode 100644 index 0000000..2b631db Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/connection/NativeHttpClient$SimpleHostnameVerifier.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/connection/NativeHttpClient$SimpleProxyAuthenticator.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/connection/NativeHttpClient$SimpleProxyAuthenticator.class new file mode 100644 index 0000000..5b0f8e1 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/connection/NativeHttpClient$SimpleProxyAuthenticator.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/connection/NativeHttpClient$SimpleTrustManager.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/connection/NativeHttpClient$SimpleTrustManager.class new file mode 100644 index 0000000..8a12983 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/connection/NativeHttpClient$SimpleTrustManager.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/connection/NativeHttpClient.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/connection/NativeHttpClient.class new file mode 100644 index 0000000..fae7ba4 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/connection/NativeHttpClient.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/resp/APIConnectionException.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/resp/APIConnectionException.class new file mode 100644 index 0000000..0aef24d Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/resp/APIConnectionException.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/resp/APIRequestException.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/resp/APIRequestException.class new file mode 100644 index 0000000..307fec6 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/resp/APIRequestException.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/resp/BaseResult.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/resp/BaseResult.class new file mode 100644 index 0000000..970f424 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/resp/BaseResult.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/resp/BooleanResult.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/resp/BooleanResult.class new file mode 100644 index 0000000..40876c5 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/resp/BooleanResult.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/resp/DefaultResult.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/resp/DefaultResult.class new file mode 100644 index 0000000..af3910a Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/resp/DefaultResult.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/resp/IRateLimiting.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/resp/IRateLimiting.class new file mode 100644 index 0000000..cd5841f Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/resp/IRateLimiting.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/resp/ResponseWrapper$ErrorEntity.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/resp/ResponseWrapper$ErrorEntity.class new file mode 100644 index 0000000..a5005c7 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/resp/ResponseWrapper$ErrorEntity.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/resp/ResponseWrapper$ErrorObject.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/resp/ResponseWrapper$ErrorObject.class new file mode 100644 index 0000000..d37fadc Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/resp/ResponseWrapper$ErrorObject.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/resp/ResponseWrapper.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/resp/ResponseWrapper.class new file mode 100644 index 0000000..db9dc46 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/common/resp/ResponseWrapper.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/device/AliasDeviceListResult.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/device/AliasDeviceListResult.class new file mode 100644 index 0000000..edaae48 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/device/AliasDeviceListResult.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/device/DeviceClient$1.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/device/DeviceClient$1.class new file mode 100644 index 0000000..6c0e444 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/device/DeviceClient$1.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/device/DeviceClient.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/device/DeviceClient.class new file mode 100644 index 0000000..cc95d20 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/device/DeviceClient.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/device/OnlineStatus.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/device/OnlineStatus.class new file mode 100644 index 0000000..5511f82 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/device/OnlineStatus.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/device/TagAliasResult.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/device/TagAliasResult.class new file mode 100644 index 0000000..9f21849 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/device/TagAliasResult.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/device/TagListResult.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/device/TagListResult.class new file mode 100644 index 0000000..6491697 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/device/TagListResult.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/examples/DevcieExample.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/examples/DevcieExample.class new file mode 100644 index 0000000..9bb5004 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/examples/DevcieExample.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/examples/PushExample.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/examples/PushExample.class new file mode 100644 index 0000000..d42517b Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/examples/PushExample.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/examples/ReportsExample.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/examples/ReportsExample.class new file mode 100644 index 0000000..88d7bd4 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/examples/ReportsExample.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/examples/ScheduleExample.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/examples/ScheduleExample.class new file mode 100644 index 0000000..8e9cc43 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/examples/ScheduleExample.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/PushClient.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/PushClient.class new file mode 100644 index 0000000..af0dbc0 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/PushClient.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/PushResult.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/PushResult.class new file mode 100644 index 0000000..5ad297a Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/PushResult.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/Message$1.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/Message$1.class new file mode 100644 index 0000000..045535f Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/Message$1.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/Message$Builder.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/Message$Builder.class new file mode 100644 index 0000000..fc2de28 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/Message$Builder.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/Message.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/Message.class new file mode 100644 index 0000000..2e24212 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/Message.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/Options$1.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/Options$1.class new file mode 100644 index 0000000..81ec651 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/Options$1.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/Options$Builder.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/Options$Builder.class new file mode 100644 index 0000000..647bcd2 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/Options$Builder.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/Options.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/Options.class new file mode 100644 index 0000000..5a21c52 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/Options.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/Platform$1.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/Platform$1.class new file mode 100644 index 0000000..32cca0f Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/Platform$1.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/Platform$Builder.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/Platform$Builder.class new file mode 100644 index 0000000..f85c42b Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/Platform$Builder.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/Platform.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/Platform.class new file mode 100644 index 0000000..1153d49 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/Platform.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/PushModel.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/PushModel.class new file mode 100644 index 0000000..1a5aad3 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/PushModel.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/PushPayload$1.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/PushPayload$1.class new file mode 100644 index 0000000..a0e8e26 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/PushPayload$1.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/PushPayload$Builder.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/PushPayload$Builder.class new file mode 100644 index 0000000..5e3cde6 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/PushPayload$Builder.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/PushPayload.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/PushPayload.class new file mode 100644 index 0000000..edb68bb Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/PushPayload.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/audience/Audience$1.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/audience/Audience$1.class new file mode 100644 index 0000000..6c9998b Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/audience/Audience$1.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/audience/Audience$Builder.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/audience/Audience$Builder.class new file mode 100644 index 0000000..96e700b Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/audience/Audience$Builder.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/audience/Audience.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/audience/Audience.class new file mode 100644 index 0000000..2b4c683 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/audience/Audience.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/audience/AudienceTarget$1.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/audience/AudienceTarget$1.class new file mode 100644 index 0000000..bf4a7b0 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/audience/AudienceTarget$1.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/audience/AudienceTarget$Builder.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/audience/AudienceTarget$Builder.class new file mode 100644 index 0000000..81fb775 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/audience/AudienceTarget$Builder.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/audience/AudienceTarget.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/audience/AudienceTarget.class new file mode 100644 index 0000000..67dc73d Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/audience/AudienceTarget.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/audience/AudienceType.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/audience/AudienceType.class new file mode 100644 index 0000000..7be5de0 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/audience/AudienceType.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/AndroidNotification$1.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/AndroidNotification$1.class new file mode 100644 index 0000000..c0c0031 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/AndroidNotification$1.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/AndroidNotification$Builder.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/AndroidNotification$Builder.class new file mode 100644 index 0000000..e155188 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/AndroidNotification$Builder.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/AndroidNotification.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/AndroidNotification.class new file mode 100644 index 0000000..c39ae93 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/AndroidNotification.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/IosAlert$1.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/IosAlert$1.class new file mode 100644 index 0000000..296c21e Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/IosAlert$1.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/IosAlert$Builder.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/IosAlert$Builder.class new file mode 100644 index 0000000..32f258e Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/IosAlert$Builder.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/IosAlert.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/IosAlert.class new file mode 100644 index 0000000..df7eabc Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/IosAlert.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/IosNotification$1.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/IosNotification$1.class new file mode 100644 index 0000000..cadaf11 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/IosNotification$1.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/IosNotification$Builder.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/IosNotification$Builder.class new file mode 100644 index 0000000..2b5cf41 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/IosNotification$Builder.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/IosNotification.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/IosNotification.class new file mode 100644 index 0000000..0ffdd40 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/IosNotification.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/Notification$1.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/Notification$1.class new file mode 100644 index 0000000..349c10f Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/Notification$1.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/Notification$Builder.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/Notification$Builder.class new file mode 100644 index 0000000..801a6cb Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/Notification$Builder.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/Notification.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/Notification.class new file mode 100644 index 0000000..17f8260 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/Notification.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/PlatformNotification$Builder.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/PlatformNotification$Builder.class new file mode 100644 index 0000000..6904123 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/PlatformNotification$Builder.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/PlatformNotification.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/PlatformNotification.class new file mode 100644 index 0000000..d4e203a Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/PlatformNotification.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/WinphoneNotification$1.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/WinphoneNotification$1.class new file mode 100644 index 0000000..cd13a9e Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/WinphoneNotification$1.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/WinphoneNotification$Builder.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/WinphoneNotification$Builder.class new file mode 100644 index 0000000..88d31a3 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/WinphoneNotification$Builder.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/WinphoneNotification.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/WinphoneNotification.class new file mode 100644 index 0000000..895ee5a Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/push/model/notification/WinphoneNotification.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/report/MessagesResult$1.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/report/MessagesResult$1.class new file mode 100644 index 0000000..70f5a49 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/report/MessagesResult$1.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/report/MessagesResult$Android.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/report/MessagesResult$Android.class new file mode 100644 index 0000000..96a7eab Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/report/MessagesResult$Android.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/report/MessagesResult$Ios.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/report/MessagesResult$Ios.class new file mode 100644 index 0000000..d44350f Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/report/MessagesResult$Ios.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/report/MessagesResult$Message.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/report/MessagesResult$Message.class new file mode 100644 index 0000000..2469e32 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/report/MessagesResult$Message.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/report/MessagesResult.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/report/MessagesResult.class new file mode 100644 index 0000000..c243d09 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/report/MessagesResult.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/report/ReceivedsResult$1.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/report/ReceivedsResult$1.class new file mode 100644 index 0000000..23fea83 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/report/ReceivedsResult$1.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/report/ReceivedsResult$Received.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/report/ReceivedsResult$Received.class new file mode 100644 index 0000000..962f0fe Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/report/ReceivedsResult$Received.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/report/ReceivedsResult.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/report/ReceivedsResult.class new file mode 100644 index 0000000..c7af5a7 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/report/ReceivedsResult.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/report/ReportClient.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/report/ReportClient.class new file mode 100644 index 0000000..6a08ade Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/report/ReportClient.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/report/UsersResult$Android.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/report/UsersResult$Android.class new file mode 100644 index 0000000..74b8b8e Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/report/UsersResult$Android.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/report/UsersResult$Ios.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/report/UsersResult$Ios.class new file mode 100644 index 0000000..f76a6e3 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/report/UsersResult$Ios.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/report/UsersResult$User.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/report/UsersResult$User.class new file mode 100644 index 0000000..78e6702 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/report/UsersResult$User.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/report/UsersResult.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/report/UsersResult.class new file mode 100644 index 0000000..b18ebb4 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/report/UsersResult.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/schedule/ScheduleClient.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/schedule/ScheduleClient.class new file mode 100644 index 0000000..41a65e7 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/schedule/ScheduleClient.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/schedule/ScheduleListResult.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/schedule/ScheduleListResult.class new file mode 100644 index 0000000..9f10557 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/schedule/ScheduleListResult.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/schedule/ScheduleResult.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/schedule/ScheduleResult.class new file mode 100644 index 0000000..278a7f0 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/schedule/ScheduleResult.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/schedule/model/IModel.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/schedule/model/IModel.class new file mode 100644 index 0000000..38c82d1 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/schedule/model/IModel.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/schedule/model/SchedulePayload$1.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/schedule/model/SchedulePayload$1.class new file mode 100644 index 0000000..6adfdde Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/schedule/model/SchedulePayload$1.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/schedule/model/SchedulePayload$Builder.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/schedule/model/SchedulePayload$Builder.class new file mode 100644 index 0000000..8739e19 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/schedule/model/SchedulePayload$Builder.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/schedule/model/SchedulePayload.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/schedule/model/SchedulePayload.class new file mode 100644 index 0000000..2e3e39d Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/schedule/model/SchedulePayload.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/schedule/model/TriggerPayload$1.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/schedule/model/TriggerPayload$1.class new file mode 100644 index 0000000..49f1064 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/schedule/model/TriggerPayload$1.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/schedule/model/TriggerPayload$Builder.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/schedule/model/TriggerPayload$Builder.class new file mode 100644 index 0000000..0f164e0 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/schedule/model/TriggerPayload$Builder.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/schedule/model/TriggerPayload$Type.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/schedule/model/TriggerPayload$Type.class new file mode 100644 index 0000000..0d5d704 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/schedule/model/TriggerPayload$Type.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/schedule/model/TriggerPayload.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/schedule/model/TriggerPayload.class new file mode 100644 index 0000000..0cf12b6 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/schedule/model/TriggerPayload.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/utils/Base64.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/utils/Base64.class new file mode 100644 index 0000000..c381cb7 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/utils/Base64.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/utils/Nullable.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/utils/Nullable.class new file mode 100644 index 0000000..aa02d22 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/utils/Nullable.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/utils/Preconditions.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/utils/Preconditions.class new file mode 100644 index 0000000..3d8a594 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/utils/Preconditions.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/utils/StringUtils.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/utils/StringUtils.class new file mode 100644 index 0000000..2674273 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/utils/StringUtils.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/jpush/utils/TimeUtils.class b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/utils/TimeUtils.class new file mode 100644 index 0000000..e0ea33a Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/jpush/utils/TimeUtils.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/netease/CheckSumBuilder.class b/target/quartzPro/WEB-INF/classes/com/ifish/netease/CheckSumBuilder.class new file mode 100644 index 0000000..3402a48 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/netease/CheckSumBuilder.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/netease/NeteaseIM.class b/target/quartzPro/WEB-INF/classes/com/ifish/netease/NeteaseIM.class new file mode 100644 index 0000000..6cf7635 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/netease/NeteaseIM.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/tianqi/javaDemo.class b/target/quartzPro/WEB-INF/classes/com/ifish/tianqi/javaDemo.class new file mode 100644 index 0000000..b108dbb Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/tianqi/javaDemo.class differ diff --git a/target/quartzPro/WEB-INF/classes/com/ifish/util/IfishUtil.class b/target/quartzPro/WEB-INF/classes/com/ifish/util/IfishUtil.class new file mode 100644 index 0000000..2e76395 Binary files /dev/null and b/target/quartzPro/WEB-INF/classes/com/ifish/util/IfishUtil.class differ diff --git a/target/quartzPro/WEB-INF/classes/jPpush.properties b/target/quartzPro/WEB-INF/classes/jPpush.properties new file mode 100644 index 0000000..4c46f36 --- /dev/null +++ b/target/quartzPro/WEB-INF/classes/jPpush.properties @@ -0,0 +1,16 @@ +#极光推送 +#appKey +jpush.android.appKey=d970d5e193cb2a0bbe41653c +#secret +jpush.android.secret=60162c8cf195ce9f4dc76629 +#production +jpush.android.productionMode=true +#appKey +jpush.ios.appKey=d147124018074eb970474e48 +#secret +jpush.ios.secret=a7d41825e75082b13675c326 +#production +jpush.ios.productionMode=true +#云信IM +netease.appKey=87b0e3315dfc2df08060bcb54246da68 +netease.appSecret=e62f6c247b46 diff --git a/target/quartzPro/WEB-INF/classes/jdbc.properties b/target/quartzPro/WEB-INF/classes/jdbc.properties new file mode 100644 index 0000000..f20d58c --- /dev/null +++ b/target/quartzPro/WEB-INF/classes/jdbc.properties @@ -0,0 +1,32 @@ +c3p0.driverClassName=com.mysql.jdbc.Driver +c3p0.url=jdbc\:mysql\://localhost\:3306/myfishdb?characterEncoding\=UTF-8 +c3p0.username=ifish +c3p0.password=ifish7pwd +#c3p0.username=root +#c3p0.password=123456 + +c3p0.autoCommitOnClose=true +c3p0.initialPoolSize=50 +c3p0.minPoolSize=50 +c3p0.maxPoolSize=100 +c3p0.acquireIncrement=3 + +c3p0.checkoutTimeout=5000 +c3p0.maxIdleTime=7200 +c3p0.idleConnectionTestPeriod=18000 +#c3p0.maxIdleTimeExcessConnections=1800 + +#c3p0.automaticTestTable=C3P0TestTable +#c3p0.testConnectionOnCheckout=false +#c3p0.testConnectionOnCheckin=false + +#org.hibernate.dialect.MySQLInnoDBDialect +hibernate.dialect=org.hibernate.dialect.MySQLDialect +hibernate.show_sql=false +hibernate.format_sql=true +hibernate.hbm2ddl.auto=false +hibernate.jdbc.batch_size=50 +hibernate.query.substitutions=true 1,false 0 +hibernate.cache.use_second_level_cache=false +hibernate.cache.use_query_cache=false +hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory \ No newline at end of file diff --git a/target/quartzPro/WEB-INF/classes/logback.xml b/target/quartzPro/WEB-INF/classes/logback.xml new file mode 100644 index 0000000..9b6a574 --- /dev/null +++ b/target/quartzPro/WEB-INF/classes/logback.xml @@ -0,0 +1,37 @@ + + + + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger{50} %msg%n + + + + + + ${LOG_HOME}/quartzPro/localhost.log + + ${LOG_HOME}/quartzPro/%d{yyyy-MM-dd}.log + 30 + + 100MB + + + + %d{yyyy-MM-dd HH:mm:ss} 【%-5level】 【%logger{50}】 %msg%n + UTF-8 + + + WARN + + + + + + + + + + + \ No newline at end of file diff --git a/target/quartzPro/WEB-INF/classes/quartz.xml b/target/quartzPro/WEB-INF/classes/quartz.xml new file mode 100644 index 0000000..83e47c3 --- /dev/null +++ b/target/quartzPro/WEB-INF/classes/quartz.xml @@ -0,0 +1,85 @@ + + + + + + + + + + + + + true + + + + + + + + + + + + + 0 0 10 * * ? + + + + + + + + + + + pushRemind + + + + + + + + + + + + + + + + + ${jpush.ios.appKey} + + + + ${jpush.ios.secret} + + + + ${jpush.ios.productionMode} + + + + + + + ${netease.appKey} + + + + ${netease.appSecret} + + + \ No newline at end of file diff --git a/target/quartzPro/WEB-INF/lib/antlr-2.7.7.jar b/target/quartzPro/WEB-INF/lib/antlr-2.7.7.jar new file mode 100644 index 0000000..5e5f14b Binary files /dev/null and b/target/quartzPro/WEB-INF/lib/antlr-2.7.7.jar differ diff --git a/target/quartzPro/WEB-INF/lib/aopalliance-1.0.jar b/target/quartzPro/WEB-INF/lib/aopalliance-1.0.jar new file mode 100644 index 0000000..578b1a0 Binary files /dev/null and b/target/quartzPro/WEB-INF/lib/aopalliance-1.0.jar differ diff --git a/target/quartzPro/WEB-INF/lib/aspectjweaver-1.8.5.jar b/target/quartzPro/WEB-INF/lib/aspectjweaver-1.8.5.jar new file mode 100644 index 0000000..952a8e4 Binary files /dev/null and b/target/quartzPro/WEB-INF/lib/aspectjweaver-1.8.5.jar differ diff --git a/target/quartzPro/WEB-INF/lib/c3p0-0.9.1.2.jar b/target/quartzPro/WEB-INF/lib/c3p0-0.9.1.2.jar new file mode 100644 index 0000000..0f42d60 Binary files /dev/null and b/target/quartzPro/WEB-INF/lib/c3p0-0.9.1.2.jar differ diff --git a/target/quartzPro/WEB-INF/lib/commons-beanutils-1.8.0.jar b/target/quartzPro/WEB-INF/lib/commons-beanutils-1.8.0.jar new file mode 100644 index 0000000..caf7ae3 Binary files /dev/null and b/target/quartzPro/WEB-INF/lib/commons-beanutils-1.8.0.jar differ diff --git a/target/quartzPro/WEB-INF/lib/commons-codec-1.6.jar b/target/quartzPro/WEB-INF/lib/commons-codec-1.6.jar new file mode 100644 index 0000000..ee1bc49 Binary files /dev/null and b/target/quartzPro/WEB-INF/lib/commons-codec-1.6.jar differ diff --git a/target/quartzPro/WEB-INF/lib/commons-collections-3.2.1.jar b/target/quartzPro/WEB-INF/lib/commons-collections-3.2.1.jar new file mode 100644 index 0000000..c35fa1f Binary files /dev/null and b/target/quartzPro/WEB-INF/lib/commons-collections-3.2.1.jar differ diff --git a/target/quartzPro/WEB-INF/lib/commons-lang-2.5.jar b/target/quartzPro/WEB-INF/lib/commons-lang-2.5.jar new file mode 100644 index 0000000..ae491da Binary files /dev/null and b/target/quartzPro/WEB-INF/lib/commons-lang-2.5.jar differ diff --git a/target/quartzPro/WEB-INF/lib/commons-logging-1.1.1.jar b/target/quartzPro/WEB-INF/lib/commons-logging-1.1.1.jar new file mode 100644 index 0000000..1deef14 Binary files /dev/null and b/target/quartzPro/WEB-INF/lib/commons-logging-1.1.1.jar differ diff --git a/target/quartzPro/WEB-INF/lib/dom4j-1.6.1.jar b/target/quartzPro/WEB-INF/lib/dom4j-1.6.1.jar new file mode 100644 index 0000000..c8c4dbb Binary files /dev/null and b/target/quartzPro/WEB-INF/lib/dom4j-1.6.1.jar differ diff --git a/target/quartzPro/WEB-INF/lib/ezmorph-1.0.6.jar b/target/quartzPro/WEB-INF/lib/ezmorph-1.0.6.jar new file mode 100644 index 0000000..30fad12 Binary files /dev/null and b/target/quartzPro/WEB-INF/lib/ezmorph-1.0.6.jar differ diff --git a/target/quartzPro/WEB-INF/lib/gson-2.3.jar b/target/quartzPro/WEB-INF/lib/gson-2.3.jar new file mode 100644 index 0000000..a7f7ce5 Binary files /dev/null and b/target/quartzPro/WEB-INF/lib/gson-2.3.jar differ diff --git a/target/quartzPro/WEB-INF/lib/hibernate-commons-annotations-4.0.5.Final.jar b/target/quartzPro/WEB-INF/lib/hibernate-commons-annotations-4.0.5.Final.jar new file mode 100644 index 0000000..6b13dce Binary files /dev/null and b/target/quartzPro/WEB-INF/lib/hibernate-commons-annotations-4.0.5.Final.jar differ diff --git a/target/quartzPro/WEB-INF/lib/hibernate-core-4.3.11.Final.jar b/target/quartzPro/WEB-INF/lib/hibernate-core-4.3.11.Final.jar new file mode 100644 index 0000000..7711cbe Binary files /dev/null and b/target/quartzPro/WEB-INF/lib/hibernate-core-4.3.11.Final.jar differ diff --git a/target/quartzPro/WEB-INF/lib/hibernate-jpa-2.1-api-1.0.0.Final.jar b/target/quartzPro/WEB-INF/lib/hibernate-jpa-2.1-api-1.0.0.Final.jar new file mode 100644 index 0000000..e2f2c59 Binary files /dev/null and b/target/quartzPro/WEB-INF/lib/hibernate-jpa-2.1-api-1.0.0.Final.jar differ diff --git a/target/quartzPro/WEB-INF/lib/httpclient-4.3.5.jar b/target/quartzPro/WEB-INF/lib/httpclient-4.3.5.jar new file mode 100644 index 0000000..1db1225 Binary files /dev/null and b/target/quartzPro/WEB-INF/lib/httpclient-4.3.5.jar differ diff --git a/target/quartzPro/WEB-INF/lib/httpcore-4.3.2.jar b/target/quartzPro/WEB-INF/lib/httpcore-4.3.2.jar new file mode 100644 index 0000000..813ec23 Binary files /dev/null and b/target/quartzPro/WEB-INF/lib/httpcore-4.3.2.jar differ diff --git a/target/quartzPro/WEB-INF/lib/jandex-1.1.0.Final.jar b/target/quartzPro/WEB-INF/lib/jandex-1.1.0.Final.jar new file mode 100644 index 0000000..6348ac2 Binary files /dev/null and b/target/quartzPro/WEB-INF/lib/jandex-1.1.0.Final.jar differ diff --git a/target/quartzPro/WEB-INF/lib/javassist-3.18.1-GA.jar b/target/quartzPro/WEB-INF/lib/javassist-3.18.1-GA.jar new file mode 100644 index 0000000..d5f19ac Binary files /dev/null and b/target/quartzPro/WEB-INF/lib/javassist-3.18.1-GA.jar differ diff --git a/target/quartzPro/WEB-INF/lib/javax.servlet-api-3.0.1.jar b/target/quartzPro/WEB-INF/lib/javax.servlet-api-3.0.1.jar new file mode 100644 index 0000000..4e2edcc Binary files /dev/null and b/target/quartzPro/WEB-INF/lib/javax.servlet-api-3.0.1.jar differ diff --git a/target/quartzPro/WEB-INF/lib/jboss-logging-3.1.3.GA.jar b/target/quartzPro/WEB-INF/lib/jboss-logging-3.1.3.GA.jar new file mode 100644 index 0000000..ff3a103 Binary files /dev/null and b/target/quartzPro/WEB-INF/lib/jboss-logging-3.1.3.GA.jar differ diff --git a/target/quartzPro/WEB-INF/lib/jboss-logging-annotations-2.0.1.Final.jar b/target/quartzPro/WEB-INF/lib/jboss-logging-annotations-2.0.1.Final.jar new file mode 100644 index 0000000..b61c614 Binary files /dev/null and b/target/quartzPro/WEB-INF/lib/jboss-logging-annotations-2.0.1.Final.jar differ diff --git a/target/quartzPro/WEB-INF/lib/jboss-transaction-api_1.2_spec-1.0.0.Final.jar b/target/quartzPro/WEB-INF/lib/jboss-transaction-api_1.2_spec-1.0.0.Final.jar new file mode 100644 index 0000000..7817dc1 Binary files /dev/null and b/target/quartzPro/WEB-INF/lib/jboss-transaction-api_1.2_spec-1.0.0.Final.jar differ diff --git a/target/quartzPro/WEB-INF/lib/json-20090211.jar b/target/quartzPro/WEB-INF/lib/json-20090211.jar new file mode 100644 index 0000000..ef29094 Binary files /dev/null and b/target/quartzPro/WEB-INF/lib/json-20090211.jar differ diff --git a/target/quartzPro/WEB-INF/lib/json-lib-2.4-jdk15.jar b/target/quartzPro/WEB-INF/lib/json-lib-2.4-jdk15.jar new file mode 100644 index 0000000..68d4f3b Binary files /dev/null and b/target/quartzPro/WEB-INF/lib/json-lib-2.4-jdk15.jar differ diff --git a/target/quartzPro/WEB-INF/lib/logback-classic-1.1.2.jar b/target/quartzPro/WEB-INF/lib/logback-classic-1.1.2.jar new file mode 100644 index 0000000..9230b2a Binary files /dev/null and b/target/quartzPro/WEB-INF/lib/logback-classic-1.1.2.jar differ diff --git a/target/quartzPro/WEB-INF/lib/logback-core-1.1.2.jar b/target/quartzPro/WEB-INF/lib/logback-core-1.1.2.jar new file mode 100644 index 0000000..391da64 Binary files /dev/null and b/target/quartzPro/WEB-INF/lib/logback-core-1.1.2.jar differ diff --git a/target/quartzPro/WEB-INF/lib/mysql-connector-5.1.8.jar b/target/quartzPro/WEB-INF/lib/mysql-connector-5.1.8.jar new file mode 100644 index 0000000..5a7c6fb Binary files /dev/null and b/target/quartzPro/WEB-INF/lib/mysql-connector-5.1.8.jar differ diff --git a/target/quartzPro/WEB-INF/lib/quartz-2.2.1.jar b/target/quartzPro/WEB-INF/lib/quartz-2.2.1.jar new file mode 100644 index 0000000..7cf3ca4 Binary files /dev/null and b/target/quartzPro/WEB-INF/lib/quartz-2.2.1.jar differ diff --git a/target/quartzPro/WEB-INF/lib/slf4j-api-1.7.12.jar b/target/quartzPro/WEB-INF/lib/slf4j-api-1.7.12.jar new file mode 100644 index 0000000..51e2fad Binary files /dev/null and b/target/quartzPro/WEB-INF/lib/slf4j-api-1.7.12.jar differ diff --git a/target/quartzPro/WEB-INF/lib/spring-aop-4.1.6.RELEASE.jar b/target/quartzPro/WEB-INF/lib/spring-aop-4.1.6.RELEASE.jar new file mode 100644 index 0000000..ca4aa29 Binary files /dev/null and b/target/quartzPro/WEB-INF/lib/spring-aop-4.1.6.RELEASE.jar differ diff --git a/target/quartzPro/WEB-INF/lib/spring-aspects-4.1.6.RELEASE.jar b/target/quartzPro/WEB-INF/lib/spring-aspects-4.1.6.RELEASE.jar new file mode 100644 index 0000000..7b5d78a Binary files /dev/null and b/target/quartzPro/WEB-INF/lib/spring-aspects-4.1.6.RELEASE.jar differ diff --git a/target/quartzPro/WEB-INF/lib/spring-beans-4.1.6.RELEASE.jar b/target/quartzPro/WEB-INF/lib/spring-beans-4.1.6.RELEASE.jar new file mode 100644 index 0000000..7206d00 Binary files /dev/null and b/target/quartzPro/WEB-INF/lib/spring-beans-4.1.6.RELEASE.jar differ diff --git a/target/quartzPro/WEB-INF/lib/spring-context-4.1.6.RELEASE.jar b/target/quartzPro/WEB-INF/lib/spring-context-4.1.6.RELEASE.jar new file mode 100644 index 0000000..6c48963 Binary files /dev/null and b/target/quartzPro/WEB-INF/lib/spring-context-4.1.6.RELEASE.jar differ diff --git a/target/quartzPro/WEB-INF/lib/spring-context-support-4.1.6.RELEASE.jar b/target/quartzPro/WEB-INF/lib/spring-context-support-4.1.6.RELEASE.jar new file mode 100644 index 0000000..84715f8 Binary files /dev/null and b/target/quartzPro/WEB-INF/lib/spring-context-support-4.1.6.RELEASE.jar differ diff --git a/target/quartzPro/WEB-INF/lib/spring-core-4.1.6.RELEASE.jar b/target/quartzPro/WEB-INF/lib/spring-core-4.1.6.RELEASE.jar new file mode 100644 index 0000000..fe5f612 Binary files /dev/null and b/target/quartzPro/WEB-INF/lib/spring-core-4.1.6.RELEASE.jar differ diff --git a/target/quartzPro/WEB-INF/lib/spring-expression-4.1.6.RELEASE.jar b/target/quartzPro/WEB-INF/lib/spring-expression-4.1.6.RELEASE.jar new file mode 100644 index 0000000..a1ceae1 Binary files /dev/null and b/target/quartzPro/WEB-INF/lib/spring-expression-4.1.6.RELEASE.jar differ diff --git a/target/quartzPro/WEB-INF/lib/spring-jdbc-4.1.6.RELEASE.jar b/target/quartzPro/WEB-INF/lib/spring-jdbc-4.1.6.RELEASE.jar new file mode 100644 index 0000000..ac4667f Binary files /dev/null and b/target/quartzPro/WEB-INF/lib/spring-jdbc-4.1.6.RELEASE.jar differ diff --git a/target/quartzPro/WEB-INF/lib/spring-orm-4.1.6.RELEASE.jar b/target/quartzPro/WEB-INF/lib/spring-orm-4.1.6.RELEASE.jar new file mode 100644 index 0000000..463719e Binary files /dev/null and b/target/quartzPro/WEB-INF/lib/spring-orm-4.1.6.RELEASE.jar differ diff --git a/target/quartzPro/WEB-INF/lib/spring-tx-4.1.6.RELEASE.jar b/target/quartzPro/WEB-INF/lib/spring-tx-4.1.6.RELEASE.jar new file mode 100644 index 0000000..28e70b0 Binary files /dev/null and b/target/quartzPro/WEB-INF/lib/spring-tx-4.1.6.RELEASE.jar differ diff --git a/target/quartzPro/WEB-INF/lib/spring-web-4.1.6.RELEASE.jar b/target/quartzPro/WEB-INF/lib/spring-web-4.1.6.RELEASE.jar new file mode 100644 index 0000000..902e9fc Binary files /dev/null and b/target/quartzPro/WEB-INF/lib/spring-web-4.1.6.RELEASE.jar differ diff --git a/target/quartzPro/WEB-INF/lib/spring-webmvc-4.1.6.RELEASE.jar b/target/quartzPro/WEB-INF/lib/spring-webmvc-4.1.6.RELEASE.jar new file mode 100644 index 0000000..749fdd0 Binary files /dev/null and b/target/quartzPro/WEB-INF/lib/spring-webmvc-4.1.6.RELEASE.jar differ diff --git a/target/quartzPro/WEB-INF/lib/xml-apis-1.0.b2.jar b/target/quartzPro/WEB-INF/lib/xml-apis-1.0.b2.jar new file mode 100644 index 0000000..ad33a5a Binary files /dev/null and b/target/quartzPro/WEB-INF/lib/xml-apis-1.0.b2.jar differ diff --git a/target/quartzPro/WEB-INF/web.xml b/target/quartzPro/WEB-INF/web.xml new file mode 100644 index 0000000..4a43aef --- /dev/null +++ b/target/quartzPro/WEB-INF/web.xml @@ -0,0 +1,17 @@ + + + Archetype Created Web Application + + index.jsp + + + contextConfigLocation + + classpath:quartz.xml + + + + org.springframework.web.context.ContextLoaderListener + + + \ No newline at end of file diff --git a/target/quartzPro/index.jsp b/target/quartzPro/index.jsp new file mode 100644 index 0000000..2560447 --- /dev/null +++ b/target/quartzPro/index.jsp @@ -0,0 +1,11 @@ +<%@ page language="java" pageEncoding="utf-8"%> + + + + 首页 + + + +

    访问正常

    + + diff --git a/target/test-classes/.netbeans_automatic_build b/target/test-classes/.netbeans_automatic_build new file mode 100644 index 0000000..e69de29