package com.elminster.retrieve.psn.service; import java.io.File; import java.io.IOException; import java.text.MessageFormat; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.codehaus.jackson.map.ObjectMapper; import com.elminster.common.constants.Constants.StringConstants; import com.elminster.common.parser.IParser; import com.elminster.common.parser.ParseException; import com.elminster.common.retrieve.RetrieveException; import com.elminster.common.util.ExceptionUtil; import com.elminster.common.util.FileUtil; import com.elminster.retrieve.psn.constants.PropertyKey; import com.elminster.retrieve.psn.data.game.PSNGame; import com.elminster.retrieve.psn.data.game.PSNTrophy; import com.elminster.retrieve.psn.data.json.JsonCompareTrophies; import com.elminster.retrieve.psn.data.json.JsonGameList; import com.elminster.retrieve.psn.data.json.JsonUserProfile; import com.elminster.retrieve.psn.data.user.PSNUserGame; import com.elminster.retrieve.psn.data.user.PSNUserProfile; import com.elminster.retrieve.psn.data.user.PSNUserTrophy; import com.elminster.retrieve.psn.exception.ServiceException; import com.elminster.retrieve.psn.parser.UserGameListParser; import com.elminster.retrieve.psn.parser.UserGameTrophyParser; import com.elminster.retrieve.psn.parser.UserProfileParser; import com.elminster.retrieve.psn.runnable.BaseRetriever; import com.elminster.retrieve.psn.runnable.CompareGameRetriever; import com.elminster.retrieve.psn.util.Configuration; /** * The implementation of PSN API. * * @author jgu * @version 1.0 */ public class PSNApiImpl implements IPSNApi { /** the logger. */ private static final Log logger = LogFactory.getLog(PSNApiImpl.class); /** * {@inheritDoc} */ @Override public PSNUserProfile getPSNUserProfile(String psnUsername) throws ServiceException { String userProfileUrl = Configuration.INSTANCE.getStringProperty(PropertyKey.PSN_USER_PROFILE_URL); long current = System.currentTimeMillis(); String url = MessageFormat.format(userProfileUrl, psnUsername, String.valueOf(current) /* the magic number for current time*/); BaseRetriever retriever = new BaseRetriever(url); try { String json = retriever.retrieve().getBody(); if (logger.isDebugEnabled()) { logger.debug("received json: " + json); } ObjectMapper mapper = new ObjectMapper(); JsonUserProfile jsonUserProfile = mapper.readValue(json, JsonUserProfile.class); IParser<JsonUserProfile, PSNUserProfile> userProfileParser = new UserProfileParser(); return userProfileParser.parse(jsonUserProfile); } catch (RetrieveException | IOException | ParseException e) { logger.error(ExceptionUtil.getFullStackTrace(e)); throw new ServiceException("Failed to get user profile for user: [" + psnUsername + "]. Caused by: " + e); } } /** * {@inheritDoc} */ @Override public List<PSNUserGame> getPSNUserGameList(String psnUsername) throws ServiceException { String userGameListUrl = Configuration.INSTANCE.getStringProperty(PropertyKey.PSN_USER_GAME_LIST_URL); long current = System.currentTimeMillis(); String url = MessageFormat.format(userGameListUrl, psnUsername, String.valueOf(current) /* the magic number for current time*/); BaseRetriever retriever = new BaseRetriever(url); try { String json = retriever.retrieve().getBody(); if (logger.isDebugEnabled()) { logger.debug("received json: " + json); } ObjectMapper mapper = new ObjectMapper(); JsonGameList jsonGameList = mapper.readValue(json, JsonGameList.class); IParser<JsonGameList, List<PSNUserGame>> userGameListParser = new UserGameListParser(); return userGameListParser.parse(jsonGameList); } catch (RetrieveException | IOException | ParseException e) { logger.error(ExceptionUtil.getFullStackTrace(e)); throw new ServiceException("Failed to get user's game list for user: [" + psnUsername + "]. Caused by: " + e); } } /** * {@inheritDoc} */ @Override public List<PSNUserTrophy> getPSNUserGameTrophies(String psnUsername, String psnGameId) throws ServiceException { String compareGameUrl = Configuration.INSTANCE.getStringProperty(PropertyKey.PSN_COMPARE_GAME_URL); File cookieFile = new File(BaseRetriever.COOKIE_FILE); if (!cookieFile.exists()) { getPSNUserProfile("test"); } try { String userinfo = getCookieValue("userinfo"); long current = System.currentTimeMillis(); // magic number 0.0xxxxxxxxxxxxxxxx double magicNumber = Math.random(); String url = MessageFormat.format(compareGameUrl, psnGameId, psnUsername, userinfo, String.valueOf(current), String.valueOf(magicNumber)); BaseRetriever retriever = new CompareGameRetriever(url); String json = retriever.retrieve().getBody(); if (logger.isDebugEnabled()) { logger.debug("received json: " + json); } ObjectMapper mapper = new ObjectMapper(); JsonCompareTrophies jsonCompareTrophies = mapper.readValue(json, JsonCompareTrophies.class); IParser<JsonCompareTrophies, List<PSNUserTrophy>> userGameTrophyParser = new UserGameTrophyParser(); return userGameTrophyParser.parse(jsonCompareTrophies); } catch (RetrieveException | IOException | ParseException e) { logger.error(ExceptionUtil.getFullStackTrace(e)); throw new ServiceException("Failed to get user's game achievement for user: [" + psnUsername + "], gameId: [" + psnGameId + "]. Caused by: " + e); } } /** * {@inheritDoc} */ @Override public List<PSNTrophy> getPSNGameTrophies(String psnGameId) throws ServiceException { throw new UnsupportedOperationException("Unsupported yet."); } /** * {@inheritDoc} */ @Override public PSNGame getPSNGameSummary(String psnGameId) throws ServiceException { throw new UnsupportedOperationException("Unsupported yet."); } /** * Get the userinfo cookie. * @throws IOException on error */ public String getCookieValue(String key) throws IOException { File cookieFile = new File(BaseRetriever.COOKIE_FILE); if (cookieFile.exists()) { String cookieInfo = FileUtil.readFile2String(cookieFile.getAbsolutePath()); if (null != cookieInfo) { String[] cookies = cookieInfo.split(StringConstants.AND); for (String cookie : cookies) { int idx = cookie.indexOf(StringConstants.EQUAL); String cookieKey = cookie.substring(0, idx); if (key.equals(cookieKey)) { String value = cookie.substring(idx + 1); if (logger.isDebugEnabled()) { logger.debug("cookie: " + cookieKey + "=" + value); } return value.replaceAll(StringConstants.EQUAL, "%3D").replaceAll(StringConstants.SLASH, "%2F"); } } } } throw new IllegalStateException(key + " is not available."); } }