Skip to content

Commit 7aedcb5

Browse files
committed
Merge pull request #14 from jpush/dev
modify common for jmessage, fix msgid bug.
2 parents 718e680 + d2107cc commit 7aedcb5

File tree

9 files changed

+107
-29
lines changed

9 files changed

+107
-29
lines changed

README.md

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
<dependency>
2525
<groupId>cn.jpush.api</groupId>
2626
<artifactId>jpush-client</artifactId>
27-
<version>3.2.3</version>
27+
<version>3.2.5</version>
2828
</dependency>
2929
```
3030
### jar 包方式
@@ -86,7 +86,7 @@
8686

8787
> 以下片断来自项目代码里的文件:example / cn.jpush.api.examples.PushExample
8888
89-
```
89+
```Java
9090
JPushClient jpushClient = new JPushClient(masterSecret, appKey, 3);
9191

9292
// For push, all you need do is to build PushPayload object.
@@ -114,15 +114,15 @@
114114

115115
* 快捷地构建推送对象:所有平台,所有设备,内容为 ALERT 的通知。
116116

117-
```
117+
```Java
118118
public static PushPayload buildPushObject_all_all_alert() {
119119
return PushPayload.alertAll(ALERT);
120120
}
121121
```
122122

123123
* 构建推送对象:所有平台,推送目标是别名为 "alias1",通知内容为 ALERT。
124124

125-
```
125+
```Java
126126
public static PushPayload buildPushObject_all_alias_alert() {
127127
return PushPayload.newBuilder()
128128
.setPlatform(Platform.all())
@@ -134,7 +134,7 @@
134134

135135
* 构建推送对象:平台是 Android,目标是 tag 为 "tag1" 的设备,内容是 Android 通知 ALERT,并且标题为 TITLE。
136136

137-
```
137+
```Java
138138
public static PushPayload buildPushObject_android_tag_alertWithTitle() {
139139
return PushPayload.newBuilder()
140140
.setPlatform(Platform.android())
@@ -146,7 +146,7 @@
146146

147147
* 构建推送对象:平台是 iOS,推送目标是 "tag1", "tag_all" 的并集,推送内容同时包括通知与消息 - 通知信息是 ALERT,角标数字为 5,通知声音为 "happy",并且附加字段 from = "JPush";消息内容是 MSG_CONTENT。通知是 APNs 推送通道的,消息是 JPush 应用内消息通道的。APNs 的推送环境是“生产”(如果不显式设置的话,Library 会默认指定为开发)
148148

149-
```
149+
```Java
150150
public static PushPayload buildPushObject_ios_tagAnd_alertWithExtrasAndMessage() {
151151
return PushPayload.newBuilder()
152152
.setPlatform(Platform.ios())
@@ -169,7 +169,7 @@
169169

170170
* 构建推送对象:平台是 Andorid 与 iOS,推送目标是 ("tag1" 与 "tag2" 的交集)并("alias1" 与 "alias2" 的交集),推送内容是 - 内容为 MSG_CONTENT 的消息,并且附加字段 from = JPush。
171171

172-
```
172+
```Java
173173
public static PushPayload buildPushObject_ios_audienceMore_messageWithExtras() {
174174
return PushPayload.newBuilder()
175175
.setPlatform(Platform.android_ios())
@@ -189,7 +189,7 @@
189189

190190
> 以下片断来自项目代码里的文件:example / cn.jpush.api.examples.ReportsExample
191191
192-
```
192+
```Java
193193
JPushClient jpushClient = new JPushClient(masterSecret, appKey);
194194
try {
195195
ReceivedsResult result = jpushClient.getReportReceiveds("1942377665");
@@ -212,7 +212,7 @@
212212

213213
> 以下片断来自项目代码里的文件:example / cn.jpush.api.examples.DeviceExample
214214
215-
```
215+
```Java
216216
try {
217217
TagAliasResult result = jpushClient.getDeviceTagAlias(REGISTRATION_ID1);
218218

@@ -229,4 +229,3 @@
229229
LOG.info("Error Message: " + e.getErrorMessage());
230230
}
231231
```
232-

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
<groupId>cn.jpush.api</groupId>
55
<artifactId>jpush-client</artifactId>
6-
<version>3.2.4-SNAPSHOT</version>
6+
<version>3.2.5-SNAPSHOT</version>
77
<packaging>jar</packaging>
88
<url>https://github.com/jpush/jpush-api-java-client</url>
99
<name>JPush API Java Client</name>

src/main/java/cn/jpush/api/common/ServiceHelper.java

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package cn.jpush.api.common;
22

3+
import java.text.SimpleDateFormat;
34
import java.util.Random;
45
import java.util.Set;
56
import java.util.regex.Pattern;
@@ -9,9 +10,12 @@
910

1011
import com.google.gson.JsonArray;
1112
import com.google.gson.JsonPrimitive;
13+
import org.slf4j.Logger;
14+
import org.slf4j.LoggerFactory;
1215

1316
public class ServiceHelper {
1417

18+
private static final Logger LOG = LoggerFactory.getLogger(ServiceHelper.class);
1519
private final static Pattern PUSH_PATTERNS = Pattern.compile("[^a-zA-Z0-9]");
1620
private final static String BASIC_PREFIX = "Basic";
1721

@@ -20,8 +24,15 @@ public class ServiceHelper {
2024
private static final int MAX = Integer.MAX_VALUE;
2125

2226
private static final int MAX_BADGE_NUMBER = 99999;
23-
24-
27+
28+
private static final Pattern USERNAME_PATTERN = Pattern.compile("^[a-zA-Z0-9][a-zA-Z_0-9.、。@,-]*");
29+
private static final Pattern DATE_PATTERN = Pattern.compile("[0-9]{4}-[0-9]{2}-[0-9]{2}");
30+
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
31+
32+
static {
33+
DATE_FORMAT.setLenient(false);
34+
}
35+
2536
public static boolean isValidIntBadge(int intBadge) {
2637
if (intBadge >= 0 && intBadge <= MAX_BADGE_NUMBER) {
2738
return true;
@@ -37,7 +48,7 @@ public static String getBasicAuthorization(String username, String password) {
3748
String encodeKey = username + ":" + password;
3849
return BASIC_PREFIX + " " + String.valueOf(Base64.encode(encodeKey.getBytes()));
3950
}
40-
51+
4152
public static void checkBasic(String appKey, String masterSecret) {
4253
if (StringUtils.isEmpty(appKey)
4354
|| StringUtils.isEmpty(masterSecret)) {
@@ -63,4 +74,21 @@ public static JsonArray fromSet(Set<String> sets) {
6374
return array;
6475
}
6576

77+
public static boolean checkUsername(String username) {
78+
return USERNAME_PATTERN.matcher(username).matches();
79+
}
80+
81+
public static boolean isValidBirthday( String birthday) {
82+
try {
83+
if( ! DATE_PATTERN.matcher(birthday).matches() ) {
84+
return false;
85+
}
86+
DATE_FORMAT.parse(birthday);
87+
} catch (Exception e) {
88+
LOG.error("incorrect date format. " + birthday, e);
89+
return false;
90+
}
91+
return true;
92+
}
93+
6694
}

src/main/java/cn/jpush/api/common/connection/HttpProxy.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import cn.jpush.api.utils.Preconditions;
1111

1212
public class HttpProxy {
13-
private static final Logger LOG = LoggerFactory.getLogger(NativeHttpClient.class);
13+
private static final Logger LOG = LoggerFactory.getLogger(HttpProxy.class);
1414

1515
private String host;
1616
private int port;

src/main/java/cn/jpush/api/common/connection/IHttpClient.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ public interface IHttpClient {
2323
public enum RequestMethod {
2424
GET,
2525
POST,
26+
PUT,
2627
DELETE
2728
}
2829

@@ -63,4 +64,6 @@ public ResponseWrapper sendPost(String url, String content)
6364
throws APIConnectionException, APIRequestException;
6465

6566

67+
public ResponseWrapper sendPut(String url, String content)
68+
throws APIConnectionException, APIRequestException;
6669
}

src/main/java/cn/jpush/api/common/connection/NativeHttpClient.java

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,15 @@
2626
import cn.jpush.api.common.resp.APIRequestException;
2727
import cn.jpush.api.common.resp.ResponseWrapper;
2828

29+
/**
30+
* The implementation has no connection pool mechanism, used origin java connection.
31+
*
32+
* 本实现没有连接池机制,基于 Java 原始的 HTTP 连接实现。
33+
*
34+
* 遇到连接超时,会自动重连指定的次数(默认为 3);如果是读取超时,则不会自动重连。
35+
*
36+
* 可选支持 HTTP 代理,同时支持 2 种方式:1) HTTP 头上加上 Proxy-Authorization 信息;2)全局配置 Authenticator.setDefault;
37+
*/
2938
public class NativeHttpClient implements IHttpClient {
3039
private static final Logger LOG = LoggerFactory.getLogger(NativeHttpClient.class);
3140
private static final String KEYWORDS_CONNECT_TIMED_OUT = "connect timed out";
@@ -35,6 +44,9 @@ public class NativeHttpClient implements IHttpClient {
3544
private String _authCode;
3645
private HttpProxy _proxy;
3746

47+
/**
48+
* 默认的重连次数是 3
49+
*/
3850
public NativeHttpClient(String authCode) {
3951
this(authCode, DEFAULT_MAX_RETRY_TIMES, null);
4052
}
@@ -46,6 +58,11 @@ public NativeHttpClient(String authCode, int maxRetryTimes, HttpProxy proxy) {
4658
this._authCode = authCode;
4759
this._proxy = proxy;
4860

61+
if ( null != _proxy && _proxy.isAuthenticationNeeded()) {
62+
Authenticator.setDefault(new SimpleProxyAuthenticator(
63+
_proxy.getUsername(), _proxy.getPassword()));
64+
}
65+
4966
initSSL();
5067
}
5168

@@ -63,6 +80,11 @@ public ResponseWrapper sendPost(String url, String content)
6380
throws APIConnectionException, APIRequestException {
6481
return doRequest(url, content, RequestMethod.POST);
6582
}
83+
84+
public ResponseWrapper sendPut(String url, String content)
85+
throws APIConnectionException, APIRequestException {
86+
return doRequest(url, content, RequestMethod.PUT);
87+
}
6688

6789
public ResponseWrapper doRequest(String url, String content,
6890
RequestMethod method) throws APIConnectionException, APIRequestException {
@@ -108,8 +130,6 @@ private ResponseWrapper _doRequest(String url, String content,
108130
conn = (HttpURLConnection) aUrl.openConnection(_proxy.getNetProxy());
109131
if (_proxy.isAuthenticationNeeded()) {
110132
conn.setRequestProperty("Proxy-Authorization", _proxy.getProxyAuthorization());
111-
Authenticator.setDefault(new SimpleProxyAuthenticator(
112-
_proxy.getUsername(), _proxy.getPassword()));
113133
}
114134
} else {
115135
conn = (HttpURLConnection) aUrl.openConnection();
@@ -124,14 +144,14 @@ private ResponseWrapper _doRequest(String url, String content,
124144
conn.setRequestProperty("Accept-Charset", CHARSET);
125145
conn.setRequestProperty("Charset", CHARSET);
126146
conn.setRequestProperty("Authorization", _authCode);
127-
147+
conn.setRequestProperty("Content-Type", CONTENT_TYPE_JSON);
148+
128149
if (RequestMethod.GET == method) {
129150
conn.setDoOutput(false);
130151
} else if (RequestMethod.DELETE == method) {
131152
conn.setDoOutput(false);
132-
} else if (RequestMethod.POST == method) {
153+
} else if (RequestMethod.POST == method || RequestMethod.PUT == method) {
133154
conn.setDoOutput(true);
134-
conn.setRequestProperty("Content-Type", CONTENT_TYPE_JSON);
135155
byte[] data = content.getBytes(CHARSET);
136156
conn.setRequestProperty("Content-Length", String.valueOf(data.length));
137157
out = conn.getOutputStream();
@@ -141,7 +161,7 @@ private ResponseWrapper _doRequest(String url, String content,
141161

142162
int status = conn.getResponseCode();
143163
InputStream in = null;
144-
if (status == 200) {
164+
if (status / 100 == 2) {
145165
in = conn.getInputStream();
146166
} else {
147167
in = conn.getErrorStream();
@@ -165,11 +185,11 @@ private ResponseWrapper _doRequest(String url, String content,
165185
String reset = conn.getHeaderField(RATE_LIMIT_Reset);
166186
wrapper.setRateLimit(quota, remaining, reset);
167187

168-
if (status == 200) {
169-
LOG.debug("Succeed to get response - 200 OK");
188+
if (status >= 200 && status < 300) {
189+
LOG.debug("Succeed to get response OK - responseCode:" + status);
170190
LOG.debug("Response Content - " + responseContent);
171191

172-
} else if (status > 200 && status < 400) {
192+
} else if (status >= 300 && status < 400) {
173193
LOG.warn("Normal response but unexpected - responseCode:" + status + ", responseContent:" + responseContent);
174194

175195
} else {
@@ -185,7 +205,7 @@ private ResponseWrapper _doRequest(String url, String content,
185205
wrapper.setErrorObject();
186206
break;
187207
case 403:
188-
LOG.error("Request is forbidden! Maybe your appkey is listed in blacklist?");
208+
LOG.error("Request is forbidden! Maybe your appkey is listed in blacklist or your params is invalid.");
189209
wrapper.setErrorObject();
190210
break;
191211
case 410:

src/main/java/cn/jpush/api/common/resp/ResponseWrapper.java

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package cn.jpush.api.common.resp;
22

3+
import com.google.gson.JsonSyntaxException;
34
import org.slf4j.Logger;
45
import org.slf4j.LoggerFactory;
56

@@ -35,11 +36,26 @@ public void setRateLimit(String quota, String remaining, String reset) {
3536
}
3637

3738
public void setErrorObject() {
38-
error = _gson.fromJson(responseContent, ErrorObject.class);
39+
try {
40+
error = _gson.fromJson(responseContent, ErrorObject.class);
41+
} catch (JsonSyntaxException e) {
42+
int index = responseContent.indexOf("error");
43+
if( -1 != index ) {
44+
int from = responseContent.indexOf("{", index);
45+
int to = responseContent.indexOf("}", from);
46+
String errorStr = responseContent.substring(from, to + 1);
47+
error = new ErrorObject();
48+
try {
49+
error.error = _gson.fromJson(errorStr, ErrorEntity.class);
50+
} catch (JsonSyntaxException e1) {
51+
LOG.error("unknown response content:" + responseContent, e);
52+
}
53+
}
54+
}
3955
}
4056

4157
public boolean isServerResponse() {
42-
if (responseCode == 200) return true;
58+
if (responseCode / 100 == 2) return true;
4359
if (responseCode > 0 && null != error && error.error.code > 0) return true;
4460
return false;
4561
}

src/main/java/cn/jpush/api/report/ReportClient.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,11 +103,11 @@ public static void checkMsgids(String msgIds) {
103103
for (String s : splits) {
104104
s = s.trim();
105105
if (!StringUtils.isEmpty(s)) {
106-
Integer.parseInt(s);
106+
Long.parseLong(s);
107107
}
108108
}
109109
} catch (NumberFormatException e) {
110-
throw new IllegalArgumentException("Every msg_id should be valid Integer number which splits by ','");
110+
throw new IllegalArgumentException("Every msg_id should be valid Long number which splits by ','");
111111
}
112112
}
113113

src/main/java/cn/jpush/api/utils/StringUtils.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,5 +73,17 @@ public static boolean isNotEmpty(String s) {
7373
return s != null && s.length() > 0;
7474
}
7575

76+
public static boolean isLineBroken(String s) {
77+
if ( null == s ) {
78+
return false;
79+
}
80+
if (s.contains("\n")) {
81+
return true;
82+
}
83+
if (s.contains("\r\n")) {
84+
return true;
85+
}
86+
return false;
87+
}
7688

7789
}

0 commit comments

Comments
 (0)