PageRenderTime 58ms CodeModel.GetById 32ms RepoModel.GetById 1ms app.codeStats 0ms

/src/com/google/android/gcm/demo/server/SendAllMessagesServlet.java

https://bitbucket.org/goffity/google-cloud-message
Java | 152 lines | 104 code | 13 blank | 35 comment | 18 complexity | a74998926aad6d9ec672e4e0dccdbdfc MD5 | raw file
  1. /*
  2. * Copyright 2012 Google Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5. * use this file except in compliance with the License. You may obtain a copy of
  6. * the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.google.android.gcm.demo.server;
  17. import com.google.android.gcm.server.Constants;
  18. import com.google.android.gcm.server.Message;
  19. import com.google.android.gcm.server.MulticastResult;
  20. import com.google.android.gcm.server.Result;
  21. import com.google.android.gcm.server.Sender;
  22. import java.io.IOException;
  23. import java.util.ArrayList;
  24. import java.util.List;
  25. import java.util.concurrent.Executor;
  26. import java.util.concurrent.Executors;
  27. import java.util.logging.Level;
  28. import javax.servlet.ServletConfig;
  29. import javax.servlet.ServletException;
  30. import javax.servlet.http.HttpServletRequest;
  31. import javax.servlet.http.HttpServletResponse;
  32. /**
  33. * Servlet that adds a new message to all registered devices.
  34. * <p>
  35. * This servlet is used just by the browser (i.e., not device).
  36. */
  37. @SuppressWarnings("serial")
  38. public class SendAllMessagesServlet extends BaseServlet {
  39. private static final int MULTICAST_SIZE = 1000;
  40. private Sender sender;
  41. private static final Executor threadPool = Executors.newFixedThreadPool(5);
  42. @Override
  43. public void init(ServletConfig config) throws ServletException {
  44. super.init(config);
  45. sender = newSender(config);
  46. }
  47. /**
  48. * Creates the {@link Sender} based on the servlet settings.
  49. */
  50. protected Sender newSender(ServletConfig config) {
  51. String key = (String) config.getServletContext()
  52. .getAttribute(ApiKeyInitializer.ATTRIBUTE_ACCESS_KEY);
  53. return new Sender(key);
  54. }
  55. /**
  56. * Processes the request to add a new message.
  57. */
  58. @Override
  59. protected void doPost(HttpServletRequest req, HttpServletResponse resp)
  60. throws IOException, ServletException {
  61. List<String> devices = Datastore.getDevices();
  62. String status;
  63. if (devices.isEmpty()) {
  64. status = "Message ignored as there is no device registered!";
  65. } else {
  66. // NOTE: check below is for demonstration purposes; a real application
  67. // could always send a multicast, even for just one recipient
  68. if (devices.size() == 1) {
  69. // send a single message using plain post
  70. String registrationId = devices.get(0);
  71. Message message = new Message.Builder().build();
  72. Result result = sender.send(message, registrationId, 5);
  73. status = "Sent message to one device: " + result;
  74. } else {
  75. // send a multicast message using JSON
  76. // must split in chunks of 1000 devices (GCM limit)
  77. int total = devices.size();
  78. List<String> partialDevices = new ArrayList<String>(total);
  79. int counter = 0;
  80. int tasks = 0;
  81. for (String device : devices) {
  82. counter++;
  83. partialDevices.add(device);
  84. int partialSize = partialDevices.size();
  85. if (partialSize == MULTICAST_SIZE || counter == total) {
  86. asyncSend(partialDevices);
  87. partialDevices.clear();
  88. tasks++;
  89. }
  90. }
  91. status = "Asynchronously sending " + tasks + " multicast messages to " +
  92. total + " devices";
  93. }
  94. }
  95. req.setAttribute(HomeServlet.ATTRIBUTE_STATUS, status.toString());
  96. getServletContext().getRequestDispatcher("/home").forward(req, resp);
  97. }
  98. private void asyncSend(List<String> partialDevices) {
  99. // make a copy
  100. final List<String> devices = new ArrayList<String>(partialDevices);
  101. threadPool.execute(new Runnable() {
  102. public void run() {
  103. Message message = new Message.Builder().build();
  104. MulticastResult multicastResult;
  105. try {
  106. multicastResult = sender.send(message, devices, 5);
  107. } catch (IOException e) {
  108. logger.log(Level.SEVERE, "Error posting messages", e);
  109. return;
  110. }
  111. List<Result> results = multicastResult.getResults();
  112. // analyze the results
  113. for (int i = 0; i < devices.size(); i++) {
  114. String regId = devices.get(i);
  115. Result result = results.get(i);
  116. String messageId = result.getMessageId();
  117. if (messageId != null) {
  118. logger.fine("Succesfully sent message to device: " + regId +
  119. "; messageId = " + messageId);
  120. String canonicalRegId = result.getCanonicalRegistrationId();
  121. if (canonicalRegId != null) {
  122. // same device has more than on registration id: update it
  123. logger.info("canonicalRegId " + canonicalRegId);
  124. Datastore.updateRegistration(regId, canonicalRegId);
  125. }
  126. } else {
  127. String error = result.getErrorCodeName();
  128. if (error.equals(Constants.ERROR_NOT_REGISTERED)) {
  129. // application has been removed from device - unregister it
  130. logger.info("Unregistered device: " + regId);
  131. Datastore.unregister(regId);
  132. } else {
  133. logger.severe("Error sending message to " + regId + ": " + error);
  134. }
  135. }
  136. }
  137. }});
  138. }
  139. }