Java tutorial
/* * Copyright 2012 Google Inc. * * 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 sk.gymdb.thinis.gcm.web; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.Transformer; import sk.gymdb.thinis.gcm.server.*; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.logging.Level; /** * THIS WILL GO AWAY LATER WHEN WE IMPLEMENT OUR OWN SENDING MECHANISM * Servlet that adds a new message to all registered devices. * <p/> * This servlet is used just by the browser (i.e., not device). */ @SuppressWarnings("serial") public class SendAllMessagesServlet extends BaseServlet { private static final int MULTICAST_SIZE = 1000; private Sender sender; private static final Executor threadPool = Executors.newFixedThreadPool(5); @Override public void init(ServletConfig config) throws ServletException { super.init(config); sender = newSender(config); } /** * Creates the {@link Sender} based on the servlet settings. */ protected Sender newSender(ServletConfig config) { String key = (String) config.getServletContext().getAttribute(ApiKeyInitializer.ATTRIBUTE_ACCESS_KEY); return new Sender(key); } /** * Processes the request to add a new message. */ @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { List<Registration> devices = Datastore.getDevices(); String status; if (devices.isEmpty()) { status = "Message ignored as there is no device registered!"; } else { // NOTE: check below is for demonstration purposes; a real application // could always send a multicast, even for just one recipient if (devices.size() == 1) { // send a single message using plain post String registrationId = devices.get(0).getId(); Message.Builder builder = new Message.Builder(); builder.addData("SPRAVA", "TOTO SA MUSI ZOBRAZIT"); Message message = builder.build(); Result result = sender.send(message, registrationId, 5); status = "Sent message to one device: " + result; } else { // send a multicast message using JSON // must split in chunks of 1000 devices (GCM limit) int total = devices.size(); List<Registration> partialDevices = new ArrayList<Registration>(total); int counter = 0; int tasks = 0; for (Registration device : devices) { counter++; partialDevices.add(device); int partialSize = partialDevices.size(); if (partialSize == MULTICAST_SIZE || counter == total) { asyncSend(partialDevices); partialDevices.clear(); tasks++; } } status = "Asynchronously sending " + tasks + " multicast messages to " + total + " devices"; } } req.setAttribute(HomeServlet.ATTRIBUTE_STATUS, status.toString()); getServletContext().getRequestDispatcher("/home").forward(req, resp); } private void asyncSend(List<Registration> partialDevices) { // make a copy final List<Registration> devices = new ArrayList<Registration>(partialDevices); threadPool.execute(new Runnable() { public void run() { Message message = new Message.Builder().build(); MulticastResult multicastResult; try { multicastResult = sender.send(message, (List<String>) CollectionUtils.collect(devices, new Transformer() { @Override public Object transform(Object o) { return ((Registration) o).getId(); } }), 5); } catch (IOException e) { logger.log(Level.SEVERE, "Error posting messages", e); return; } List<Result> results = multicastResult.getResults(); // analyze the results for (int i = 0; i < devices.size(); i++) { // String regId = devices.get(i); Registration registration = devices.get(i); Result result = results.get(i); String messageId = result.getMessageId(); if (messageId != null) { logger.fine("Succesfully sent message to device: " + registration.getId() + "; messageId = " + messageId); Registration canonicalRegId = new Registration(result.getCanonicalRegistrationId(), registration.getClazz()); if (canonicalRegId != null) { // same device has more than on registration id: update it logger.info("canonicalRegId " + canonicalRegId); Datastore.updateRegistration(registration, canonicalRegId); } } else { String error = result.getErrorCodeName(); if (error.equals(Constants.ERROR_NOT_REGISTERED)) { // application has been removed from device - unregister it logger.info("Unregistered device: " + registration.getId()); Datastore.unregister(registration); } else { logger.severe("Error sending message to " + registration.getId() + ": " + error); } } } } }); } }