@Override
 public void setTimeout(int connectTimeout, int readTimeout) {
   request
       .getFetchOptions()
       .setDeadline(
           connectTimeout == 0 || readTimeout == 0
               ? Double.MAX_VALUE
               : (connectTimeout + readTimeout) / 1000.0);
 }
Exemple #2
0
  /** Profile info operation. */
  private long profInfoOp(
      final HttpServletRequest request,
      final HttpServletResponse response,
      final PersistenceManager pm,
      final ApiAccount apiAccount)
      throws IOException {
    LOGGER.fine("API account: " + apiAccount.getUser().getEmail());

    final Integer bnetId;
    final Integer bnetSubId;
    final String gatewayString;
    final String playerName;
    final Gateway gateway;

    final String bnetProfileUrlParam = request.getParameter(PARAM_BNET_PROFILE_URL);
    if (bnetProfileUrlParam == null || bnetProfileUrlParam.isEmpty()) {
      // Player id is provided explicitly
      bnetId = getIntParam(request, PARAM_BNET_ID);
      bnetSubId = getIntParam(request, PARAM_BNET_SUBID);
      gatewayString = request.getParameter(PARAM_GATEWAY);
      playerName = request.getParameter(PARAM_PLAYER_NAME);
      if (bnetId == null
          || bnetSubId == null
          || gatewayString == null
          || gatewayString.isEmpty()
          || playerName == null
          || playerName.isEmpty()) {
        LOGGER.warning("Missing parameters!");
        response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Missing parameters!");
        return 0;
      }
      gateway = Gateway.fromBinaryValue(gatewayString);
      if (gateway == Gateway.UNKNOWN || gateway == Gateway.PUBLIC_TEST) {
        LOGGER.warning("Invalid gateway parameter: " + gatewayString);
        response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid gateway parameter!");
        return 0;
      }
    } else {
      // Player id is provided through his/her Battle.net profile URL
      try {
        Gateway foundGateway = null;
        for (final Gateway gateway_ : EnumCache.GATEWAYS)
          if (bnetProfileUrlParam.startsWith(gateway_.bnetUrl)) {
            foundGateway = gateway_;
            break;
          }
        if (foundGateway == null
            || foundGateway == Gateway.UNKNOWN
            || foundGateway == Gateway.PUBLIC_TEST) throw new Exception("No matching gateway!");
        gateway = foundGateway;

        final String[] urlParts = bnetProfileUrlParam.split("/");
        if (urlParts.length < 3) throw new Exception("Not enough parts in URL!");

        playerName = URLDecoder.decode(urlParts[urlParts.length - 1], "UTF-8");
        bnetSubId = Integer.valueOf(urlParts[urlParts.length - 2]);
        bnetId = Integer.valueOf(urlParts[urlParts.length - 3]);

      } catch (final Exception e) {
        LOGGER.log(Level.SEVERE, "Invalid Battle.net profile URL: " + bnetProfileUrlParam, e);
        response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid Battle.net profile URL!");
        return 0;
      }
    }

    long opsCharged = 1;

    final Boolean retrieveExtInfoParam = getBooleanParam(request, PARAM_RETRIEVE_EXT_INFO);
    // Default or requested values:
    final boolean retrieveExtInfo = retrieveExtInfoParam == null ? false : retrieveExtInfoParam;

    try {
      final PlayerId playerId = new PlayerId();
      playerId.battleNetId = bnetId;
      playerId.battleNetSubId = bnetSubId;
      playerId.gateway = gateway;
      playerId.name = playerName;

      final String bnetProfileUrl = playerId.getBattleNetProfileUrl(BnetLanguage.ENGLISH);

      LOGGER.fine("Bnet profile URL: " + bnetProfileUrl);

      final URLFetchService urlFetchService = URLFetchServiceFactory.getURLFetchService();

      // Default deadline: 5 seconds... increase it!
      final HTTPRequest profileRequest = new HTTPRequest(new URL(bnetProfileUrl));
      profileRequest
          .getFetchOptions()
          .setDeadline(50.0); // 50-sec deadline (leaving 10 seconds to process...
      final Future<HTTPResponse> profileFetchAsync = urlFetchService.fetchAsync(profileRequest);

      final Future<HTTPResponse> extProfileFetchAsync;
      if (retrieveExtInfo) {
        opsCharged++;
        // Start retrieving extended profile info in parallel
        final HTTPRequest extProfileRequest =
            new HTTPRequest(new URL(bnetProfileUrl + "ladder/leagues"));
        extProfileRequest
            .getFetchOptions()
            .setDeadline(50.0); // 50-sec deadline (leaving 10 seconds to process...
        extProfileFetchAsync = urlFetchService.fetchAsync(extProfileRequest);
      } else extProfileFetchAsync = null;

      final XmlBuilder xb = new XmlBuilder("1.1");

      HTTPResponse profileResponse = null;
      Profile profile = null;
      Element profInfoElement = null;
      try {
        profileResponse = profileFetchAsync.get();

        switch (profileResponse.getResponseCode()) {
          case HttpServletResponse.SC_OK:
            {
              final byte[] content = profileResponse.getContent();
              if (content.length == 0) throw new Exception("Content length = 0!");
              profile = BnetUtils.retrieveProfile(null, new ByteArrayInputStream(content));
              if (profile != null) {
                LOGGER.fine("Parse OK");

                xb.createResultElement(ProfInfoResult.OK);
                opsCharged += 2;

                profInfoElement = xb.setParentElement(xb.createElement(XTAG_PROFILE_INFO));
                // Re-include player id
                final Element playerElement =
                    xb.createElement(XTAG_PLAYER_ID, XATTR_NAME, playerName);
                playerElement.setAttribute(XATTR_BNET_ID, bnetId.toString());
                playerElement.setAttribute(XATTR_BNET_SUBID, bnetSubId.toString());
                playerElement.setAttribute(XATTR_GATEWAY, gateway.toString());
                playerElement.setAttribute(XATTR_GW_CODE, gateway.binaryValue);
                playerElement.setAttribute(XATTR_REGION, playerId.getRegion().toString());
                playerElement.setAttribute(XATTR_PROFILE_URL, bnetProfileUrl);
                final Element portraitElement =
                    xb.createElement(XTAG_PORTRAIT, XATTR_GROUP, profile.portraitGroup);
                portraitElement.setAttribute(XATTR_ROW, Integer.toString(profile.portraitRow));
                portraitElement.setAttribute(
                    XATTR_COLUMN, Integer.toString(profile.portraitColumn));
                xb.createElement(XTAG_ACHIEVEMENT_POINTS, profile.achievementPoints);
                xb.createElement(XTAG_TOTAL_CAREER_GAMES, profile.totalCareerGames);
                xb.createElement(XTAG_GAMES_THIS_SEASON, profile.gamesThisSeason);
                xb.createElement(XTAG_TERRAN_WINS, profile.terranWins);
                xb.createElement(XTAG_ZERG_WINS, profile.zergWins);
                xb.createElement(XTAG_PROTOSS_WINS, profile.protossWins);
                final Element highestSoloFlElement =
                    xb.createElement(XTAG_HIGHEST_SOLO_FL, profile.highestSoloFinishLeague);
                if (profile.highestSoloFinishTimes > 0)
                  highestSoloFlElement.setAttribute(
                      XATTR_TIMES_ACHIEVED, Integer.toString(profile.highestSoloFinishTimes));
                final Element highestTeamFlElement =
                    xb.createElement(XTAG_HIGHEST_TEAM_FL, profile.highestTeamFinishLeague);
                if (profile.highestTeamFinishTimes > 0)
                  highestTeamFlElement.setAttribute(
                      XATTR_TIMES_ACHIEVED, Integer.toString(profile.highestTeamFinishTimes));

                break;
              } else {
                LOGGER.fine("Parse error!");
                xb.createResultElement(ProfInfoResult.PARSING_ERROR); // Parse fails
              }
            }
          case HttpServletResponse.SC_NOT_FOUND:
            LOGGER.fine("Invalid player!");
            xb.createResultElement(ProfInfoResult.INVALID_PLAYER);
            break;
          default:
            // Treat other response HTTP status codes as BNET_ERROR
            throw new Exception("Response code: " + profileResponse.getResponseCode());
        }

      } catch (final Exception e) {
        LOGGER.log(Level.SEVERE, "", e);
        xb.createResultElement(ProfInfoResult.BNET_ERROR);
      } finally {
        if (retrieveExtInfo && profile == null) extProfileFetchAsync.cancel(true);
      }

      if (retrieveExtInfo && profile != null) {
        try {
          profileResponse = extProfileFetchAsync.get();

          final byte[] content;
          if (profileResponse.getResponseCode() == HttpServletResponse.SC_OK
              && (content = profileResponse.getContent()).length > 0) {
            profile =
                BnetUtils.retrieveExtProfile(null, new ByteArrayInputStream(content), profile);
            if (profile != null) {
              LOGGER.fine("Parse extended OK");

              opsCharged += 2;
              xb.setParentElement(profInfoElement);
              final Element allRankGroupsElement =
                  xb.setParentElement(xb.createElement(XTAG_ALL_RANK_GROUPS));
              int allRankGroupsCount = 0;
              for (int bracket = 0; bracket < profile.allRankss.length; bracket++) {
                final TeamRank[] allRanks = profile.allRankss[bracket];
                if (allRanks != null && allRanks.length > 0) {
                  allRankGroupsCount++;
                  xb.setParentElement(allRankGroupsElement);
                  final Element allRankGroupElement =
                      xb.createElement(XTAG_ALL_RANK_GROUP, XATTR_COUNT, allRanks.length);
                  allRankGroupElement.setAttribute(
                      XATTR_FORMAT, (bracket + 1) + "v" + (bracket + 1));

                  for (int i = 0; i < allRanks.length; i++) {
                    xb.setParentElement(allRankGroupElement);
                    final Element teamRankElement =
                        xb.setParentElement(
                            xb.createElement(
                                XTAG_TEAM_RANK, XATTR_LEAGUE, allRanks[i].league.stringValue));
                    teamRankElement.setAttribute(
                        XATTR_DIVISION_RANK, Integer.toString(allRanks[i].divisionRank));
                    // Team members
                    xb.setParentElement(
                        xb.createElement(
                            XTAG_TEAM_MEMBERS, XATTR_COUNT, allRanks[i].teamMembers.length));
                    for (final String memberName : allRanks[i].teamMembers)
                      xb.createElement(XTAG_TEAM_MEMBER, XATTR_NAME, memberName);
                  }
                }
              }
              allRankGroupsElement.setAttribute(XATTR_COUNT, Integer.toString(allRankGroupsCount));
            } else LOGGER.fine("Parse extended error!");
          }
        } catch (final Exception e) {
          LOGGER.log(
              Level.SEVERE,
              "Failed to get extended profile info, we return the basic profile info silently.",
              e);
          // Failed to get extended profile info, we return the basic profile info silently
        }
      }

      xb.printDocument(response);

      return opsCharged;

    } catch (final Exception e) {
      LOGGER.log(Level.SEVERE, "", e);
      response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
      return 0;
    }
  }