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
+ *
+ * 需要特别留意的是,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