15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright (c) 2012 The Chromium Authors. All rights reserved.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Use of this source code is governed by a BSD-style license that can be
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * found in the LICENSE file.
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The "Hello world!" of the Chrome Web Store Licensing API, in Java. This
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * program logs the user in with OpenID, fetches their license state with OAuth,
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * and prints one of these greetings as appropriate:
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   1. Hello *no* license!
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   2. Hello *free trial* license!
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   3. Hello *full* license!
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Brian Kennish <bkennish@chromium.org>
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)package com.example;
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import java.io.*;
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import java.net.*;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import java.util.HashSet;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import javax.servlet.http.*;
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import com.google.appengine.api.users.*;
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import com.google.appengine.repackaged.org.json.JSONObject;
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import oauth.signpost.OAuthConsumer;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import oauth.signpost.basic.DefaultOAuthConsumer;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* A Google App Engine servlet. */
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)@SuppressWarnings("serial")
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public class HelloLicenseServlet extends HttpServlet {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* TODO: The app ID from the Chrome Developer Dashboard. */
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public static final String APP_ID = "[INSERT APP ID HERE]";
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* TODO: The token from the Chrome Developer Dashboard. */
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  private static final String TOKEN = "[INSERT TOKEN HERE]";
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* TODO: The token secret from the Chrome Developer Dashboard. */
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  private static final String TOKEN_SECRET = "[INSERT TOKEN SECRET HERE]";
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /*
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * The license server URL, where %s are placeholders for app and
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * user IDs
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public static final String SERVER_URL =
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "https://www.googleapis.com/chromewebstore/v1/licenses/%s/%s";
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* The consumer key. */
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public static final String CONSUMER_KEY = "anonymous";
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* The consumer secret. */
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public static final String CONSUMER_SECRET = CONSUMER_KEY;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Handles "GET" requests. */
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public void doGet(HttpServletRequest request, HttpServletResponse response)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      throws IOException {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    response.setContentType("text/html; charset=UTF-8");
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UserService userService = UserServiceFactory.getUserService();
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PrintWriter output = response.getWriter();
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    String url = request.getRequestURI();
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (userService.isUserLoggedIn()) {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Provide a logout path.
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      User user = userService.getCurrentUser();
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      output.printf(
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "<strong>%s</strong> | <a href=\"%s\">Sign out</a><br><br>",
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        user.getEmail(),
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        userService.createLogoutURL(url)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      );
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      try {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Send a signed request for the user's license state.
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        OAuthConsumer oauth =
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            new DefaultOAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        oauth.setTokenWithSecret(TOKEN, TOKEN_SECRET);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        URLConnection http =
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            new URL(
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              String.format(
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                SERVER_URL,
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                APP_ID,
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                URLEncoder.encode(user.getFederatedIdentity(), "UTF-8")
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              )
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ).openConnection();
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        oauth.sign(http);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        http.connect();
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Convert the response from the license server to a string.
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        BufferedReader input =
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            new BufferedReader(new InputStreamReader(http.getInputStream()));
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        String file = "";
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (String line; (line = input.readLine()) != null; file += line);
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        input.close();
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Parse the string as JSON and display the license state.
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        JSONObject json = new JSONObject(file);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        output.printf(
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "Hello <strong>%s</strong> license!",
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "YES".equals(json.get("result")) ?
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "FULL".equals(json.get("accessLevel")) ? "full" : "free trial" :
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "no"
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        );
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } catch (Exception exception) {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Dump any error.
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        output.printf("Oops! <strong>%s</strong>", exception.getMessage());
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else { // The user isn't logged in.
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Prompt for login.
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      output.printf(
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "<a href=\"%s\">Sign in</a>",
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        userService.createLoginURL(
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          url,
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          null,
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "https://www.google.com/accounts/o8/id",
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          new HashSet<String>()
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        )
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      );
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
118