package com.pugh.sockso;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import org.apache.log4j.Logger;
import com.google.inject.Inject;
import com.google.inject.Singleton;
@Singleton
public class CommunityUpdater extends Thread implements PropertiesListener {
private static final Logger log = Logger.getLogger( CommunityUpdater.class );
private final int MINUTES_BETWEEN_PINGS = 15;
private final Properties p;
/**
* Create a new community updater
*
* @param p
*
*/
@Inject
public CommunityUpdater( final Properties p ) {
this.p = p;
p.addPropertiesListener( this );
}
/**
* When properties are saved interrupt our wait to check if we need to
* ping the community server.
*
* @param p
*
*/
public void propertiesSaved( final Properties p ) {
this.interrupt();
}
/**
* Entry point for this thread
*
*/
@Override
public void run() {
while ( true ) {
check();
try { Thread.sleep( 1000 * 60 * MINUTES_BETWEEN_PINGS ); }
catch ( final InterruptedException e ) {}
}
}
/**
* Checks if the community is enabled for this server, and sends a ping
* if it is.
*
*/
protected void check() {
if ( p.get(Constants.COMMUNITY_ENABLED).equals(Properties.YES) ) {
ping();
}
}
/**
* Sends a ping request to the community server to inform it that we're
* alive and to update our details.
*
*/
protected void ping() {
BufferedReader in = null;
OutputStreamWriter wr = null;
try {
String line;
final String pingUrl = getPingUrl();
final HttpURLConnection cnn = getUrlConnection( pingUrl );
final String json = "{" +
" \"skey\": \"" +getKey()+ "\", " +
" \"port\": \"" +p.get(Constants.SERVER_PORT)+ "\", " +
" \"basepath\": \"" +p.get(Constants.SERVER_BASE_PATH)+ "\" " +
"}";
cnn.setDoOutput( true );
log.debug( "Ping community server: " +json );
wr = new OutputStreamWriter( cnn.getOutputStream() );
wr.write( json );
wr.flush();
in = new BufferedReader( new InputStreamReader(cnn.getInputStream()) );
while ( (line = in.readLine()) != null ) {
log.debug( "Ping response: " +line );
}
}
catch ( final IOException e ) {
log.error( e );
}
finally {
Utils.close( wr );
Utils.close( in );
}
}
/**
* Returns the connection object to use (seam for testing)
*
* @param url
*
* @return
*
* @throws IOException
*
*/
protected HttpURLConnection getUrlConnection( final String url ) throws IOException {
return (HttpURLConnection) new URL( url ).openConnection();
}
/**
* Returns the ping url, which can be specified by settings
*
* @return
*
*/
protected String getPingUrl() {
return p.get(
Constants.COMMUNITY_PING_URL,
Constants.WEBSITE_URL + "/community/ping"
);
}
/**
* Fetches the servers unique key (generating it if it doesn't exist yet)
*
* @return
*
*/
private String getKey() {
String key = p.get( Constants.SERVER_KEY, "" );
if ( key.length() == 0 ) {
key = Utils.getRandomString( 32 );
p.set( Constants.SERVER_KEY, key );
p.save();
}
return key;
}
}