package com.limegroup.gnutella.bugs; import java.io.IOException; import java.util.StringTokenizer; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.limegroup.gnutella.ErrorService; import com.limegroup.gnutella.util.URLDecoder; /** * Handles the client-side representation of an * <tt>RemoteServletInfo</tt> object, which reconstructs the data * for the update created on the server side. This parses that * information so BugManager can store it. */ //2345678|012345678|012345678|012345678|012345678|012345678|012345678|012345678| public final class RemoteClientInfo extends RemoteAbstractInfo { private static final Log LOG = LogFactory.getLog(RemoteClientInfo.class); /** * The amount of time to wait should the server be down. */ private static final long FAILURE_TIME = 60 * 60 * 1000; // 1 hour /** * The next time this particular bug can be sent. */ private String _nextThisBugTime; /** * The next time any bug can be sent. */ private String _nextAnyBugTime; /** * Adds multiple key/value pairs based on the information * in infoLine. infoLine is expected to be in the form of * 'key=URLEncoder.encode(value)&key2=URLEncode.encode(value2)' * * This method is used on the client side to reconstruct the * <tt>RemoteServletInfo</tt> object originally created on the server. * * @param infoLine string containing all name/value pairs. */ final void addRemoteInfo(final String infoLine) { if(LOG.isDebugEnabled()) LOG.debug("Adding info: " + infoLine); StringTokenizer st = new StringTokenizer(infoLine, "=&"); if( st.countTokens() % 2 != 0 ) return; //invalid response. while(st.hasMoreTokens()) { handleKeyValuePair(st.nextToken(), st.nextToken()); } } /** * Handles a single key/value pair, storing the values in this * object. * * This method is used on the client side to reconstruct the * <tt>RemoteUpdateInfo</tt> object originally created on the server. * * @param line a string representing one key-value pair of * information from the server's response */ private final void handleKeyValuePair(final String k, final String v) { String value = ""; try { value = URLDecoder.decode(v); } catch (IOException e) { // Should not happen from our own bug server. ErrorService.error(e); return; } if(k.equalsIgnoreCase(NEXT_THIS_BUG_TIME)) _nextThisBugTime = value; else if (k.equalsIgnoreCase(NEXT_ANY_BUG_TIME)) _nextAnyBugTime = value; // else something random -- don't worry about it } /** * Marks the next bug time & next any bug time for the appropriate values * given a connection failure. */ final void connectFailed() { _nextThisBugTime = "" + FAILURE_TIME; _nextAnyBugTime = "" + FAILURE_TIME; } /** * Returns the next time, as a long, that this bug is allowed to be sent. * The return value is in milliseconds, and should be added to * System.currentTimeMillis() to retrieve the exact millisecond at which * the next bug should be sent. */ long getNextThisBugTime() { if( _nextThisBugTime == null) return 0; else { long nextTime; try { nextTime = Long.parseLong(_nextThisBugTime); } catch(NumberFormatException nfe) { nextTime = 0; } return nextTime; } } /** * Returns the next time, as a long, that any bug is allowed to be sent. * The return value is in milliseconds, and should be added to * System.currentTimeMillis() to retrieve the exact millisecond at which * the next bug should be sent. */ long getNextAnyBugTime() { if( _nextAnyBugTime == null) return 0; else { long nextTime; try { nextTime = Long.parseLong(_nextAnyBugTime); } catch(NumberFormatException nfe) { nextTime = 0; } return nextTime; } } }