Project: * Clean-up (Eclipse cruft, unused files, etc...) * Git-specific changes * Maven POMs clean-up and changes for the build system * Version set to 1.0.0-0 in the development branches * Maven plug-ins updated to latest versions * Very partial dev. documentation added
This commit is contained in:
parent
c74e30d5ba
commit
0665a760de
1439 changed files with 1020 additions and 1649 deletions
legacyworlds-server-main/src
main
java/com/deepclone/lw
Main.java
cli
CLITool.javaCreateSuperuser.javaCreateUser.javaExportDB.javaImportBuildables.javaImportTechs.javaImportText.javaStop.javaTick.javaToolBase.java
dbexport
srv
resources
test
|
@ -0,0 +1,149 @@
|
|||
package com.deepclone.lw;
|
||||
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.deepclone.lw.cli.CLITool;
|
||||
import com.deepclone.lw.cli.ToolBase;
|
||||
import com.deepclone.lw.srv.Server;
|
||||
|
||||
|
||||
|
||||
public class Main
|
||||
implements Runnable
|
||||
{
|
||||
private String dataSource = "data-source.xml";
|
||||
private int port = 9137;
|
||||
private int servPort = 9138;
|
||||
private String tool = null;
|
||||
private String toolOptions[] = { };
|
||||
private ToolBase toolInstance;
|
||||
|
||||
|
||||
public Main( String[] args )
|
||||
{
|
||||
this.parseArguments( args );
|
||||
|
||||
if ( this.tool != null ) {
|
||||
this.toolInstance = CLITool.create( this.tool );
|
||||
} else {
|
||||
this.toolInstance = new Server( );
|
||||
}
|
||||
|
||||
if ( this.toolInstance == null ) {
|
||||
System.err.println( "tool " + this.tool + " not found" );
|
||||
System.exit( -1 );
|
||||
}
|
||||
|
||||
this.toolInstance.setMainSettings( this.dataSource , this.port , this.servPort );
|
||||
if ( !this.toolInstance.setOptions( this.toolOptions ) ) {
|
||||
System.err.println( "invalid tool options (" + Arrays.asList( this.toolOptions ) + ")" );
|
||||
System.exit( -1 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void run( )
|
||||
{
|
||||
this.toolInstance.run( );
|
||||
System.gc( );
|
||||
System.exit( 0 );
|
||||
}
|
||||
|
||||
|
||||
private void parseArguments( String[] args )
|
||||
{
|
||||
int state = 0;
|
||||
for ( int i = 0 ; i < args.length ; i++ ) {
|
||||
switch ( state ) {
|
||||
case 0:
|
||||
state = this.parseNextOption( args[ i ] );
|
||||
break;
|
||||
case 1:
|
||||
this.dataSource = args[ i ];
|
||||
state = 0;
|
||||
break;
|
||||
case 2:
|
||||
this.port = this.getPort( args[ i ] );
|
||||
state = 0;
|
||||
break;
|
||||
case 3:
|
||||
this.servPort = this.getPort( args[ i ] );
|
||||
state = 0;
|
||||
break;
|
||||
case 4:
|
||||
this.tool = args[ i ];
|
||||
state = 300;
|
||||
break;
|
||||
case 300:
|
||||
if ( args[ i ].startsWith( "--" ) ) {
|
||||
i--;
|
||||
} else if ( !args[ i ].equals( "" ) ) {
|
||||
this.toolOptions = args[ i ].split( "\\s+" );
|
||||
}
|
||||
state = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( state % 100 != 0 || this.port == this.servPort ) {
|
||||
this.printCommandLine( );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private int parseNextOption( String arg )
|
||||
{
|
||||
if ( "--data-source".equals( arg ) ) {
|
||||
return 1;
|
||||
} else if ( "--server-port".equals( arg ) ) {
|
||||
return 2;
|
||||
} else if ( "--service-port".equals( arg ) ) {
|
||||
return 3;
|
||||
} else if ( "--run-tool".equals( arg ) ) {
|
||||
return 4;
|
||||
}
|
||||
this.printCommandLine( );
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
private int getPort( String arg )
|
||||
{
|
||||
int port;
|
||||
try {
|
||||
port = Integer.parseInt( arg );
|
||||
} catch ( NumberFormatException e ) {
|
||||
port = 0;
|
||||
}
|
||||
if ( port < 1 || port > 65535 ) {
|
||||
this.printCommandLine( );
|
||||
return -1;
|
||||
}
|
||||
return port;
|
||||
}
|
||||
|
||||
|
||||
private void printCommandLine( )
|
||||
{
|
||||
System.err.println( "Legacy Worlds beta 6 - Game server and command line tools" );
|
||||
System.err.println( );
|
||||
System.err.println( " Command line options:" );
|
||||
System.err.println( " --data-source <path> Data source configuration file (default: "
|
||||
+ this.dataSource + ")" );
|
||||
System.err.println( " --run-tool <tool> <options> Command line tool to run (default: none)" );
|
||||
System.err.println( " --server-port <port> RMI registry port number (default: " + this.port + ")" );
|
||||
System.err.println( " --service-port <port> RMI service port number (default: " + this.servPort + ")" );
|
||||
System.err.println( );
|
||||
|
||||
System.exit( -1 );
|
||||
}
|
||||
|
||||
|
||||
public static void main( String[] args )
|
||||
{
|
||||
new Main( args ).run( );
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
package com.deepclone.lw.cli;
|
||||
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.remoting.rmi.RmiProxyFactoryBean;
|
||||
|
||||
|
||||
|
||||
public abstract class CLITool
|
||||
extends ToolBase
|
||||
{
|
||||
|
||||
private String makeRmiUrl( String service )
|
||||
{
|
||||
return "rmi://localhost:" + this.getRmiPort( ) + "/" + service;
|
||||
}
|
||||
|
||||
|
||||
private void addRMIClient( GenericApplicationContext context , String service , String iface )
|
||||
{
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition( RmiProxyFactoryBean.class );
|
||||
builder.setScope( BeanDefinition.SCOPE_PROTOTYPE );
|
||||
builder.addPropertyValue( "serviceInterface" , iface );
|
||||
builder.addPropertyValue( "serviceUrl" , this.makeRmiUrl( service ) );
|
||||
context.registerBeanDefinition( service , builder.getBeanDefinition( ) );
|
||||
}
|
||||
|
||||
|
||||
protected ApplicationContext createClientContext( String... configurationFiles )
|
||||
{
|
||||
return this.createClientContext( null , configurationFiles );
|
||||
}
|
||||
|
||||
|
||||
protected ApplicationContext createClientContext( Map< String , String > rmiServices )
|
||||
{
|
||||
return this.createClientContext( rmiServices , (String[]) null );
|
||||
}
|
||||
|
||||
|
||||
protected ApplicationContext createClientContext( Map< String , String > rmiServices , String... configurationFiles )
|
||||
{
|
||||
if ( rmiServices == null ) {
|
||||
return new ClassPathXmlApplicationContext( configurationFiles , true );
|
||||
}
|
||||
|
||||
GenericApplicationContext context = new GenericApplicationContext( );
|
||||
for ( Map.Entry< String , String > rmiService : rmiServices.entrySet( ) ) {
|
||||
this.addRMIClient( context , rmiService.getKey( ) , rmiService.getValue( ) );
|
||||
}
|
||||
context.refresh( );
|
||||
if ( configurationFiles == null ) {
|
||||
return context;
|
||||
}
|
||||
return new ClassPathXmlApplicationContext( configurationFiles , true , context );
|
||||
}
|
||||
|
||||
|
||||
public static ToolBase create( String tool )
|
||||
{
|
||||
String cName = "com.deepclone.lw.cli." + tool;
|
||||
Class< ? > toolClass;
|
||||
Object o;
|
||||
|
||||
try {
|
||||
toolClass = Class.forName( cName );
|
||||
} catch ( ClassNotFoundException e ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
o = toolClass.newInstance( );
|
||||
} catch ( Exception e ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ( ! ( o instanceof CLITool ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (ToolBase) o;
|
||||
}
|
||||
|
||||
|
||||
protected static String getLine( )
|
||||
{
|
||||
BufferedReader stdin = new BufferedReader( new InputStreamReader( System.in ) );
|
||||
do {
|
||||
try {
|
||||
return stdin.readLine( );
|
||||
} catch ( IOException e ) {
|
||||
e.printStackTrace( );
|
||||
}
|
||||
} while ( true );
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
package com.deepclone.lw.cli;
|
||||
|
||||
|
||||
import java.sql.Types;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.AbstractApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.context.support.FileSystemXmlApplicationContext;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.support.TransactionCallback;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
import com.deepclone.lw.cmd.admin.adata.Privileges;
|
||||
import com.deepclone.lw.utils.StoredProc;
|
||||
|
||||
|
||||
|
||||
public class CreateSuperuser
|
||||
extends CLITool
|
||||
{
|
||||
private final Logger logger = Logger.getLogger( CreateSuperuser.class );
|
||||
|
||||
private String address;
|
||||
private String appearAs;
|
||||
private TransactionTemplate tTemplate;
|
||||
private StoredProc fCreateAdmin;
|
||||
|
||||
|
||||
private ClassPathXmlApplicationContext getContext( )
|
||||
{
|
||||
// Load data source and Hibernate properties
|
||||
String[] dataConfig = {
|
||||
this.getDataSource( ) ,
|
||||
};
|
||||
FileSystemXmlApplicationContext ctx = new FileSystemXmlApplicationContext( dataConfig );
|
||||
ctx.refresh( );
|
||||
|
||||
// Load transaction manager bean
|
||||
String[] cfg = {
|
||||
"configuration/transaction-bean.xml"
|
||||
};
|
||||
return new ClassPathXmlApplicationContext( cfg , true , ctx );
|
||||
}
|
||||
|
||||
|
||||
private void getBeans( ApplicationContext ctx )
|
||||
{
|
||||
DataSource dSource = ctx.getBean( DataSource.class );
|
||||
PlatformTransactionManager tManager = ctx.getBean( PlatformTransactionManager.class );
|
||||
|
||||
this.tTemplate = new TransactionTemplate( tManager );
|
||||
|
||||
this.fCreateAdmin = new StoredProc( dSource , "admin" , "create_admin" );
|
||||
this.fCreateAdmin.addParameter( "address" , Types.VARCHAR );
|
||||
this.fCreateAdmin.addParameter( "appear_as" , Types.VARCHAR );
|
||||
this.fCreateAdmin.addParameter( "privileges" , Types.INTEGER );
|
||||
this.fCreateAdmin.addOutput( "err_code" , Types.INTEGER );
|
||||
this.fCreateAdmin.addOutput( "admin_id" , Types.INTEGER );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void run( )
|
||||
{
|
||||
AbstractApplicationContext ctx = this.getContext( );
|
||||
this.getBeans( ctx );
|
||||
this.createAdmin( );
|
||||
}
|
||||
|
||||
|
||||
private void createAdmin( )
|
||||
{
|
||||
int id;
|
||||
try {
|
||||
id = this.tTemplate.execute( new TransactionCallback< Integer >( ) {
|
||||
@Override
|
||||
public Integer doInTransaction( TransactionStatus status )
|
||||
{
|
||||
return doCreateAdmin( );
|
||||
}
|
||||
} );
|
||||
} catch ( RuntimeException e ) {
|
||||
this.logger.error( "administrator creation failed: " + e.getMessage( ) );
|
||||
return;
|
||||
}
|
||||
this.logger.info( "Administrator created with identifier #" + id );
|
||||
}
|
||||
|
||||
|
||||
private int doCreateAdmin( )
|
||||
{
|
||||
Map< String , Object > result;
|
||||
result = this.fCreateAdmin.execute( this.address , this.appearAs , Privileges.SUPER.getBits( ) );
|
||||
|
||||
int errCode = (Integer) result.get( "err_code" );
|
||||
switch ( errCode ) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
throw new RuntimeException( "unknown e-mail address " + this.address );
|
||||
case 2:
|
||||
throw new RuntimeException( "user with e-mail address " + this.address + " has an invalid status" );
|
||||
case 3:
|
||||
throw new RuntimeException( "administrator name " + this.appearAs + " is already in use" );
|
||||
case 4:
|
||||
throw new RuntimeException( "user with e-mail address " + this.address + " is already an administrator" );
|
||||
default:
|
||||
throw new RuntimeException( "unknown error code " + errCode );
|
||||
}
|
||||
|
||||
return (Integer) result.get( "admin_id" );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean setOptions( String... options )
|
||||
{
|
||||
if ( options.length == 2 ) {
|
||||
this.address = options[ 0 ];
|
||||
this.appearAs = options[ 1 ];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,168 @@
|
|||
package com.deepclone.lw.cli;
|
||||
|
||||
|
||||
import java.sql.Types;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.AbstractApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.context.support.FileSystemXmlApplicationContext;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.support.TransactionCallback;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
import com.deepclone.lw.utils.EmailAddress;
|
||||
import com.deepclone.lw.utils.Password;
|
||||
import com.deepclone.lw.utils.StoredProc;
|
||||
|
||||
|
||||
|
||||
public class CreateUser
|
||||
extends CLITool
|
||||
{
|
||||
|
||||
private boolean query;
|
||||
private String mailAddress;
|
||||
private String password;
|
||||
private String language;
|
||||
|
||||
private String pSha1;
|
||||
private String pMd5;
|
||||
|
||||
private TransactionTemplate tTemplate;
|
||||
private StoredProc fCreateUser;
|
||||
|
||||
|
||||
private ClassPathXmlApplicationContext getContext( )
|
||||
{
|
||||
// Load data source and Hibernate properties
|
||||
String[] dataConfig = {
|
||||
this.getDataSource( ) ,
|
||||
};
|
||||
FileSystemXmlApplicationContext ctx = new FileSystemXmlApplicationContext( dataConfig );
|
||||
ctx.refresh( );
|
||||
|
||||
// Load transaction manager bean
|
||||
String[] cfg = {
|
||||
"configuration/transaction-bean.xml"
|
||||
};
|
||||
return new ClassPathXmlApplicationContext( cfg , true , ctx );
|
||||
}
|
||||
|
||||
|
||||
private void getBeans( ApplicationContext ctx )
|
||||
{
|
||||
DataSource dSource = ctx.getBean( DataSource.class );
|
||||
PlatformTransactionManager tManager = ctx.getBean( PlatformTransactionManager.class );
|
||||
|
||||
this.tTemplate = new TransactionTemplate( tManager );
|
||||
|
||||
this.fCreateUser = new StoredProc( dSource , "users" , "create_inactive_account" );
|
||||
this.fCreateUser.addParameter( "address" , Types.VARCHAR );
|
||||
this.fCreateUser.addParameter( "lang_id" , Types.VARCHAR );
|
||||
this.fCreateUser.addParameter( "pass_md5" , Types.VARCHAR );
|
||||
this.fCreateUser.addParameter( "pass_sha1" , Types.VARCHAR );
|
||||
this.fCreateUser.addOutput( "err_code" , Types.INTEGER );
|
||||
this.fCreateUser.addOutput( "a_id" , Types.INTEGER );
|
||||
}
|
||||
|
||||
|
||||
private void queryUser( )
|
||||
{
|
||||
System.out.println( "User creation - E-mail address: " );
|
||||
this.mailAddress = CLITool.getLine( );
|
||||
System.out.println( "User creation - Password: " );
|
||||
this.password = CLITool.getLine( );
|
||||
System.out.println( "User creation - Language ID: " );
|
||||
this.language = CLITool.getLine( );
|
||||
}
|
||||
|
||||
|
||||
private boolean validate( )
|
||||
{
|
||||
EmailAddress addr = new EmailAddress( this.mailAddress );
|
||||
if ( !addr.isValid( ) ) {
|
||||
System.err.println( "Invalid mail address" );
|
||||
return false;
|
||||
}
|
||||
this.mailAddress = addr.getAddress( );
|
||||
|
||||
Password pwd = new Password( this.password );
|
||||
if ( pwd.getStrength( ) < 10 ) {
|
||||
System.err.println( "Weak password" );
|
||||
return false;
|
||||
}
|
||||
this.pSha1 = pwd.getSha1( );
|
||||
this.pMd5 = pwd.getMd5( );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private Map< String , Object > createAccount( )
|
||||
{
|
||||
return this.tTemplate.execute( new TransactionCallback< Map< String , Object > >( ) {
|
||||
@Override
|
||||
public Map< String , Object > doInTransaction( TransactionStatus status )
|
||||
{
|
||||
return fCreateUser.execute( mailAddress , language , pMd5 , pSha1 );
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void run( )
|
||||
{
|
||||
if ( this.query ) {
|
||||
this.queryUser( );
|
||||
}
|
||||
if ( !this.validate( ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
AbstractApplicationContext ctx = this.getContext( );
|
||||
this.getBeans( ctx );
|
||||
|
||||
Map< String , Object > m = this.createAccount( );
|
||||
int errCode = (Integer) m.get( "err_code" );
|
||||
switch ( errCode ) {
|
||||
case 0:
|
||||
System.out.println( "Account #" + (Integer) m.get( "a_id" ) + " created." );
|
||||
break;
|
||||
case -1:
|
||||
System.err.println( "Address in use" );
|
||||
break;
|
||||
case -2:
|
||||
System.err.println( "Invalid language" );
|
||||
break;
|
||||
}
|
||||
|
||||
ToolBase.destroyContext( ctx );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean setOptions( String... options )
|
||||
{
|
||||
if ( options.length == 0 ) {
|
||||
this.query = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( options.length == 3 ) {
|
||||
this.query = false;
|
||||
this.mailAddress = options[ 0 ];
|
||||
this.password = options[ 1 ];
|
||||
this.language = options[ 2 ];
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,176 @@
|
|||
package com.deepclone.lw.cli;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.context.support.AbstractApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.context.support.FileSystemXmlApplicationContext;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.support.TransactionCallback;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
import com.deepclone.lw.cli.dbexport.BugEventMapper;
|
||||
import com.deepclone.lw.cli.dbexport.BugGroup;
|
||||
import com.deepclone.lw.cli.dbexport.LegacyWorldsDB;
|
||||
import com.deepclone.lw.cli.dbexport.UserMapper;
|
||||
import com.thoughtworks.xstream.XStream;
|
||||
|
||||
|
||||
|
||||
public class ExportDB
|
||||
extends CLITool
|
||||
{
|
||||
|
||||
private final String sGetUsers = "SELECT ul.* , al.administrator_id , al.name AS administrator_name , al.privileges , al.pass_sha1 AS administrator_sha1 , al.pass_md5 AS administrator_md5 "
|
||||
+ "FROM admin.users_list ul LEFT OUTER JOIN admin.admins_view al on al.account_id = ul.id "
|
||||
+ "WHERE ul.status IN ('ACTIVE' , 'VACATION' , 'START_VACATION' ) OR ( ul.game_credits > 0 AND ul.status <> 'BANNED' ) OR ( al IS NOT NULL AND al.active )";
|
||||
|
||||
private final String sListGroupEvents = "SELECT group_id , event_id FROM bugs.br_first_report INNER JOIN bugs.br_status USING( group_id ) INNER JOIN bugs.events USING( group_id ) "
|
||||
+ "WHERE status <> 'NOT_A_BUG' ORDER BY group_id";
|
||||
|
||||
private final String sGetBugEvents = "SELECT be.* , asd.account_status FROM bugs.br_first_report INNER JOIN bugs.br_status s USING( group_id ) INNER JOIN bugs.br_events be USING( bug_report_id ) "
|
||||
+ "LEFT OUTER JOIN bugs.account_status_data asd USING (event_id) WHERE s.status <> 'NOT_A_BUG' ORDER BY event_id";
|
||||
|
||||
private static class LongPair
|
||||
{
|
||||
public long id1;
|
||||
public long id2;
|
||||
}
|
||||
|
||||
private static class LongPairMapper
|
||||
implements RowMapper< LongPair >
|
||||
{
|
||||
|
||||
@Override
|
||||
public LongPair mapRow( ResultSet rs , int rowNum )
|
||||
throws SQLException
|
||||
{
|
||||
LongPair lp = new LongPair( );
|
||||
lp.id1 = rs.getLong( 1 );
|
||||
lp.id2 = rs.getLong( 2 );
|
||||
return lp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private File file;
|
||||
private TransactionTemplate tTemplate;
|
||||
private SimpleJdbcTemplate dTemplate;
|
||||
|
||||
|
||||
private ClassPathXmlApplicationContext createContext( )
|
||||
{
|
||||
// Load data source
|
||||
String[] dataConfig = {
|
||||
this.getDataSource( ) ,
|
||||
};
|
||||
FileSystemXmlApplicationContext ctx = new FileSystemXmlApplicationContext( dataConfig );
|
||||
ctx.refresh( );
|
||||
|
||||
// Load transaction manager bean
|
||||
String[] cfg = {
|
||||
"configuration/transaction-bean.xml"
|
||||
};
|
||||
return new ClassPathXmlApplicationContext( cfg , true , ctx );
|
||||
}
|
||||
|
||||
|
||||
private void prepareDataAccess( AbstractApplicationContext ctx )
|
||||
{
|
||||
DataSource dSource = ctx.getBean( DataSource.class );
|
||||
PlatformTransactionManager tManager = ctx.getBean( PlatformTransactionManager.class );
|
||||
|
||||
this.tTemplate = new TransactionTemplate( tManager );
|
||||
this.dTemplate = new SimpleJdbcTemplate( dSource );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void run( )
|
||||
{
|
||||
AbstractApplicationContext ctx = this.createContext( );
|
||||
this.prepareDataAccess( ctx );
|
||||
|
||||
LegacyWorldsDB db = this.tTemplate.execute( new TransactionCallback< LegacyWorldsDB >( ) {
|
||||
@Override
|
||||
public LegacyWorldsDB doInTransaction( TransactionStatus status )
|
||||
{
|
||||
return readDB( );
|
||||
}
|
||||
} );
|
||||
|
||||
this.writeFile( db );
|
||||
}
|
||||
|
||||
|
||||
private LegacyWorldsDB readDB( )
|
||||
{
|
||||
LegacyWorldsDB db = new LegacyWorldsDB( );
|
||||
db.users = this.dTemplate.query( sGetUsers , new UserMapper( ) );
|
||||
db.bugReports.groups = this.readBugGroups( );
|
||||
db.bugReports.events = this.dTemplate.query( sGetBugEvents , new BugEventMapper( ) );
|
||||
return db;
|
||||
}
|
||||
|
||||
|
||||
private List< BugGroup > readBugGroups( )
|
||||
{
|
||||
List< BugGroup > groups = new ArrayList< BugGroup >( );
|
||||
Long prevGroupId = null;
|
||||
BugGroup current = null;
|
||||
|
||||
for ( LongPair lp : this.dTemplate.query( sListGroupEvents , new LongPairMapper( ) ) ) {
|
||||
if ( prevGroupId == null || lp.id1 != prevGroupId ) {
|
||||
prevGroupId = lp.id1;
|
||||
current = new BugGroup( );
|
||||
groups.add( current );
|
||||
}
|
||||
current.events.add( lp.id2 );
|
||||
}
|
||||
|
||||
return groups;
|
||||
}
|
||||
|
||||
|
||||
private void writeFile( LegacyWorldsDB db )
|
||||
{
|
||||
XStream xStream = new XStream( );
|
||||
xStream.autodetectAnnotations( true );
|
||||
|
||||
FileWriter file;
|
||||
try {
|
||||
file = new FileWriter( this.file );
|
||||
} catch ( IOException e ) {
|
||||
throw new RuntimeException( e );
|
||||
}
|
||||
xStream.toXML( db , file );
|
||||
try {
|
||||
file.close( );
|
||||
} catch ( IOException e ) {
|
||||
throw new RuntimeException( e );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean setOptions( String... options )
|
||||
{
|
||||
if ( options.length != 1 ) {
|
||||
return false;
|
||||
}
|
||||
this.file = new File( options[ 0 ] );
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,316 @@
|
|||
package com.deepclone.lw.cli;
|
||||
|
||||
|
||||
import java.io.*;
|
||||
import java.sql.Types;
|
||||
import java.util.List;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.AbstractApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.context.support.FileSystemXmlApplicationContext;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.support.TransactionCallback;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
import com.deepclone.lw.sqld.game.BuildingOutputType;
|
||||
import com.deepclone.lw.utils.StoredProc;
|
||||
import com.thoughtworks.xstream.XStream;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
|
||||
import com.thoughtworks.xstream.annotations.XStreamImplicit;
|
||||
|
||||
|
||||
|
||||
public class ImportBuildables
|
||||
extends CLITool
|
||||
{
|
||||
private final Logger logger = Logger.getLogger( ImportBuildables.class );
|
||||
|
||||
@SuppressWarnings( "serial" )
|
||||
@XStreamAlias( "buildables" )
|
||||
public static class BuildablesData
|
||||
implements Serializable
|
||||
{
|
||||
@XStreamImplicit
|
||||
public List< BuildableData > buildables;
|
||||
}
|
||||
|
||||
@SuppressWarnings( "serial" )
|
||||
public static abstract class BuildableData
|
||||
implements Serializable
|
||||
{
|
||||
@XStreamAsAttribute
|
||||
public String name;
|
||||
|
||||
@XStreamAsAttribute
|
||||
public String description;
|
||||
|
||||
public CostData cost;
|
||||
|
||||
public TechData tech;
|
||||
}
|
||||
|
||||
@SuppressWarnings( "serial" )
|
||||
@XStreamAlias( "cost" )
|
||||
public static class CostData
|
||||
implements Serializable
|
||||
{
|
||||
@XStreamAsAttribute
|
||||
public int build;
|
||||
|
||||
@XStreamAsAttribute
|
||||
public int upkeep;
|
||||
|
||||
@XStreamAsAttribute
|
||||
public int work;
|
||||
}
|
||||
|
||||
@SuppressWarnings( "serial" )
|
||||
@XStreamAlias( "tech" )
|
||||
public static class TechData
|
||||
implements Serializable
|
||||
{
|
||||
@XStreamAsAttribute
|
||||
public String name;
|
||||
|
||||
@XStreamAsAttribute
|
||||
public int level;
|
||||
}
|
||||
|
||||
@SuppressWarnings( "serial" )
|
||||
@XStreamAlias( "building" )
|
||||
public static class BuildingData
|
||||
extends BuildableData
|
||||
{
|
||||
@XStreamAsAttribute
|
||||
public BuildingOutputType type;
|
||||
|
||||
@XStreamAsAttribute
|
||||
public int output;
|
||||
|
||||
@XStreamAsAttribute
|
||||
public int workers;
|
||||
}
|
||||
|
||||
@SuppressWarnings( "serial" )
|
||||
@XStreamAlias( "ship" )
|
||||
public static class ShipData
|
||||
extends BuildableData
|
||||
{
|
||||
@XStreamAsAttribute
|
||||
public int time;
|
||||
|
||||
@XStreamAsAttribute
|
||||
public int power;
|
||||
}
|
||||
|
||||
private File file;
|
||||
private TransactionTemplate tTemplate;
|
||||
private StoredProc uocBuildingNoDep;
|
||||
private StoredProc uocBuildingDep;
|
||||
private StoredProc uocShipNoDep;
|
||||
private StoredProc uocShipDep;
|
||||
|
||||
|
||||
private XStream initXStream( )
|
||||
{
|
||||
XStream xstream = new XStream( );
|
||||
xstream.processAnnotations( BuildablesData.class );
|
||||
xstream.processAnnotations( BuildingData.class );
|
||||
xstream.processAnnotations( ShipData.class );
|
||||
return xstream;
|
||||
}
|
||||
|
||||
|
||||
private BuildablesData loadData( )
|
||||
{
|
||||
FileInputStream fis;
|
||||
try {
|
||||
fis = new FileInputStream( this.file );
|
||||
} catch ( FileNotFoundException e ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
XStream xstream = this.initXStream( );
|
||||
return (BuildablesData) xstream.fromXML( fis );
|
||||
} catch ( Exception e ) {
|
||||
e.printStackTrace( );
|
||||
return null;
|
||||
} finally {
|
||||
try {
|
||||
fis.close( );
|
||||
} catch ( IOException e ) {
|
||||
// EMPTY
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private ClassPathXmlApplicationContext createContext( )
|
||||
{
|
||||
// Load data source
|
||||
String[] dataConfig = {
|
||||
this.getDataSource( )
|
||||
};
|
||||
FileSystemXmlApplicationContext ctx = new FileSystemXmlApplicationContext( dataConfig );
|
||||
ctx.refresh( );
|
||||
|
||||
// Load Hibernate bean
|
||||
String[] cfg = {
|
||||
"configuration/context-configuration.xml" , "configuration/transaction-bean.xml"
|
||||
};
|
||||
return new ClassPathXmlApplicationContext( cfg , true , ctx );
|
||||
}
|
||||
|
||||
|
||||
private void createTemplates( ApplicationContext ctx )
|
||||
{
|
||||
PlatformTransactionManager tManager = ctx.getBean( PlatformTransactionManager.class );
|
||||
this.tTemplate = new TransactionTemplate( tManager );
|
||||
|
||||
DataSource dataSource = ctx.getBean( DataSource.class );
|
||||
|
||||
this.uocBuildingNoDep = new StoredProc( dataSource , "tech" , "uoc_building" );
|
||||
this.uocBuildingNoDep.addParameter( "name" , Types.VARCHAR );
|
||||
this.uocBuildingNoDep.addParameter( "description" , Types.VARCHAR );
|
||||
this.uocBuildingNoDep.addParameter( "cost" , Types.INTEGER );
|
||||
this.uocBuildingNoDep.addParameter( "work" , Types.INTEGER );
|
||||
this.uocBuildingNoDep.addParameter( "upkeep" , Types.INTEGER );
|
||||
this.uocBuildingNoDep.addParameter( "workers" , Types.INTEGER );
|
||||
this.uocBuildingNoDep.addParameter( "output_type" , "building_output_type" );
|
||||
this.uocBuildingNoDep.addParameter( "output" , Types.INTEGER );
|
||||
|
||||
this.uocBuildingDep = new StoredProc( dataSource , "tech" , "uoc_building" );
|
||||
this.uocBuildingDep.addParameter( "name" , Types.VARCHAR );
|
||||
this.uocBuildingDep.addParameter( "description" , Types.VARCHAR );
|
||||
this.uocBuildingDep.addParameter( "cost" , Types.INTEGER );
|
||||
this.uocBuildingDep.addParameter( "work" , Types.INTEGER );
|
||||
this.uocBuildingDep.addParameter( "upkeep" , Types.INTEGER );
|
||||
this.uocBuildingDep.addParameter( "workers" , Types.INTEGER );
|
||||
this.uocBuildingDep.addParameter( "output_type" , "building_output_type" );
|
||||
this.uocBuildingDep.addParameter( "output" , Types.INTEGER );
|
||||
this.uocBuildingDep.addParameter( "dep_name" , Types.VARCHAR );
|
||||
this.uocBuildingDep.addParameter( "dep_level" , Types.INTEGER );
|
||||
|
||||
this.uocShipNoDep = new StoredProc( dataSource , "tech" , "uoc_ship" );
|
||||
this.uocShipNoDep.addParameter( "name" , Types.VARCHAR );
|
||||
this.uocShipNoDep.addParameter( "description" , Types.VARCHAR );
|
||||
this.uocShipNoDep.addParameter( "cost" , Types.INTEGER );
|
||||
this.uocShipNoDep.addParameter( "work" , Types.INTEGER );
|
||||
this.uocShipNoDep.addParameter( "upkeep" , Types.INTEGER );
|
||||
this.uocShipNoDep.addParameter( "power" , Types.INTEGER );
|
||||
this.uocShipNoDep.addParameter( "flight_time" , Types.INTEGER );
|
||||
|
||||
this.uocShipDep = new StoredProc( dataSource , "tech" , "uoc_ship" );
|
||||
this.uocShipDep.addParameter( "name" , Types.VARCHAR );
|
||||
this.uocShipDep.addParameter( "description" , Types.VARCHAR );
|
||||
this.uocShipDep.addParameter( "cost" , Types.INTEGER );
|
||||
this.uocShipDep.addParameter( "work" , Types.INTEGER );
|
||||
this.uocShipDep.addParameter( "upkeep" , Types.INTEGER );
|
||||
this.uocShipDep.addParameter( "power" , Types.INTEGER );
|
||||
this.uocShipDep.addParameter( "flight_time" , Types.INTEGER );
|
||||
this.uocShipDep.addParameter( "dep_name" , Types.VARCHAR );
|
||||
this.uocShipDep.addParameter( "dep_level" , Types.INTEGER );
|
||||
}
|
||||
|
||||
|
||||
private void importBuildables( BuildablesData buildables )
|
||||
{
|
||||
for ( BuildableData buildable : buildables.buildables ) {
|
||||
if ( buildable instanceof BuildingData ) {
|
||||
this.importBuilding( (BuildingData) buildable );
|
||||
} else {
|
||||
this.importShip( (ShipData) buildable );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void importShip( ShipData ship )
|
||||
{
|
||||
this.logger.info( "Importing ship " + ship.name );
|
||||
|
||||
if ( ship.tech == null ) {
|
||||
this.uocShipNoDep.execute( ship.name , ship.description , ship.cost.build , ship.cost.work ,
|
||||
ship.cost.upkeep , ship.power , ship.time );
|
||||
} else {
|
||||
this.uocShipDep.execute( ship.name , ship.description , ship.cost.build , ship.cost.work ,
|
||||
ship.cost.upkeep , ship.power , ship.time , ship.tech.name , ship.tech.level );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void importBuilding( BuildingData building )
|
||||
{
|
||||
this.logger.info( "Importing building " + building.name );
|
||||
if ( building.tech == null ) {
|
||||
this.uocBuildingNoDep.execute( building.name , building.description , building.cost.build ,
|
||||
building.cost.work , building.cost.upkeep , building.workers , building.type.toString( ) ,
|
||||
building.output );
|
||||
} else {
|
||||
this.uocBuildingDep.execute( building.name , building.description , building.cost.build ,
|
||||
building.cost.work , building.cost.upkeep , building.workers , building.type.toString( ) ,
|
||||
building.output , building.tech.name , building.tech.level );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void run( )
|
||||
{
|
||||
final BuildablesData buildables = this.loadData( );
|
||||
AbstractApplicationContext ctx = this.createContext( );
|
||||
this.createTemplates( ctx );
|
||||
|
||||
boolean rv = this.tTemplate.execute( new TransactionCallback< Boolean >( ) {
|
||||
|
||||
@Override
|
||||
public Boolean doInTransaction( TransactionStatus status )
|
||||
{
|
||||
boolean rv;
|
||||
try {
|
||||
importBuildables( buildables );
|
||||
rv = true;
|
||||
} catch ( RuntimeException e ) {
|
||||
if ( e.getCause( ) != null ) {
|
||||
logger.error( "Exception encoutered" , e );
|
||||
}
|
||||
logger.error( e.getMessage( ) );
|
||||
rv = false;
|
||||
}
|
||||
if ( !rv ) {
|
||||
status.setRollbackOnly( );
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
if ( rv ) {
|
||||
this.logger.info( "Import successful" );
|
||||
}
|
||||
|
||||
ToolBase.destroyContext( ctx );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean setOptions( String... options )
|
||||
{
|
||||
if ( options.length != 1 ) {
|
||||
return false;
|
||||
}
|
||||
this.file = new File( options[ 0 ] );
|
||||
if ( ! ( this.file.isFile( ) && this.file.canRead( ) ) ) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,217 @@
|
|||
package com.deepclone.lw.cli;
|
||||
|
||||
|
||||
import java.io.*;
|
||||
import java.sql.Types;
|
||||
import java.util.List;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.AbstractApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.context.support.FileSystemXmlApplicationContext;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.support.TransactionCallback;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
import com.deepclone.lw.utils.StoredProc;
|
||||
import com.thoughtworks.xstream.XStream;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
|
||||
import com.thoughtworks.xstream.annotations.XStreamImplicit;
|
||||
|
||||
|
||||
|
||||
public class ImportTechs
|
||||
extends CLITool
|
||||
{
|
||||
|
||||
private final Logger logger = Logger.getLogger( ImportTechs.class );
|
||||
|
||||
@XStreamAlias( "technologies" )
|
||||
@SuppressWarnings( "serial" )
|
||||
public static class Techs
|
||||
implements Serializable
|
||||
{
|
||||
@XStreamImplicit( itemFieldName = "tech-line" )
|
||||
public List< TechLine > lines;
|
||||
}
|
||||
|
||||
@SuppressWarnings( "serial" )
|
||||
public static class TechLine
|
||||
implements Serializable
|
||||
{
|
||||
@XStreamAsAttribute
|
||||
public String name;
|
||||
|
||||
@XStreamAsAttribute
|
||||
public String description;
|
||||
|
||||
@XStreamImplicit( itemFieldName = "level" )
|
||||
public List< TechLevel > levels;
|
||||
}
|
||||
|
||||
@SuppressWarnings( "serial" )
|
||||
public static class TechLevel
|
||||
implements Serializable
|
||||
{
|
||||
@XStreamAsAttribute
|
||||
public String name;
|
||||
|
||||
@XStreamAsAttribute
|
||||
public String description;
|
||||
|
||||
@XStreamAsAttribute
|
||||
public int points;
|
||||
|
||||
@XStreamAsAttribute
|
||||
public int cost;
|
||||
}
|
||||
|
||||
private File file;
|
||||
private TransactionTemplate tTemplate;
|
||||
private StoredProc uocLine;
|
||||
private StoredProc uocLevel;
|
||||
|
||||
|
||||
private XStream initXStream( )
|
||||
{
|
||||
XStream xstream = new XStream( );
|
||||
xstream.processAnnotations( Techs.class );
|
||||
return xstream;
|
||||
}
|
||||
|
||||
|
||||
private Techs loadData( )
|
||||
{
|
||||
FileInputStream fis;
|
||||
try {
|
||||
fis = new FileInputStream( this.file );
|
||||
} catch ( FileNotFoundException e ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
XStream xstream = this.initXStream( );
|
||||
return (Techs) xstream.fromXML( fis );
|
||||
} catch ( Exception e ) {
|
||||
e.printStackTrace( );
|
||||
return null;
|
||||
} finally {
|
||||
try {
|
||||
fis.close( );
|
||||
} catch ( IOException e ) {
|
||||
// EMPTY
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private ClassPathXmlApplicationContext createContext( )
|
||||
{
|
||||
// Load data source and Hibernate properties
|
||||
String[] dataConfig = {
|
||||
this.getDataSource( )
|
||||
};
|
||||
FileSystemXmlApplicationContext ctx = new FileSystemXmlApplicationContext( dataConfig );
|
||||
ctx.refresh( );
|
||||
|
||||
// Load beans
|
||||
String[] cfg = {
|
||||
"configuration/context-configuration.xml" , "configuration/transaction-bean.xml"
|
||||
};
|
||||
return new ClassPathXmlApplicationContext( cfg , true , ctx );
|
||||
}
|
||||
|
||||
|
||||
private void getBeans( ApplicationContext ctx )
|
||||
{
|
||||
PlatformTransactionManager tManager = ctx.getBean( PlatformTransactionManager.class );
|
||||
this.tTemplate = new TransactionTemplate( tManager );
|
||||
|
||||
DataSource dataSource = ctx.getBean( DataSource.class );
|
||||
this.uocLine = new StoredProc( dataSource , "tech" , "uoc_line" );
|
||||
this.uocLine.addParameter( "tln" , Types.VARCHAR );
|
||||
this.uocLine.addParameter( "tld" , Types.VARCHAR );
|
||||
|
||||
this.uocLevel = new StoredProc( dataSource , "tech" , "uoc_level" );
|
||||
this.uocLevel.addParameter( "tech_line" , Types.VARCHAR );
|
||||
this.uocLevel.addParameter( "level" , Types.INTEGER );
|
||||
this.uocLevel.addParameter( "name" , Types.VARCHAR );
|
||||
this.uocLevel.addParameter( "desc" , Types.VARCHAR );
|
||||
this.uocLevel.addParameter( "points" , Types.INTEGER );
|
||||
this.uocLevel.addParameter( "cost" , Types.INTEGER );
|
||||
}
|
||||
|
||||
|
||||
private void importTechnologies( Techs data )
|
||||
{
|
||||
for ( TechLine line : data.lines ) {
|
||||
this.uocLine.execute( line.name , line.description );
|
||||
|
||||
int i = 1;
|
||||
for ( TechLevel level : line.levels ) {
|
||||
this.uocLevel.execute( line.name , i , level.name , level.description , level.points , level.cost );
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void run( )
|
||||
{
|
||||
final Techs data = this.loadData( );
|
||||
if ( data == null ) {
|
||||
System.err.println( "could not read data" );
|
||||
return;
|
||||
}
|
||||
|
||||
AbstractApplicationContext ctx = this.createContext( );
|
||||
this.getBeans( ctx );
|
||||
boolean rv = this.tTemplate.execute( new TransactionCallback< Boolean >( ) {
|
||||
|
||||
@Override
|
||||
public Boolean doInTransaction( TransactionStatus status )
|
||||
{
|
||||
boolean rv;
|
||||
try {
|
||||
importTechnologies( data );
|
||||
rv = true;
|
||||
} catch ( RuntimeException e ) {
|
||||
logger.error( e.getMessage( ) );
|
||||
rv = false;
|
||||
}
|
||||
if ( !rv ) {
|
||||
status.setRollbackOnly( );
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
if ( rv ) {
|
||||
this.logger.info( "Import successful" );
|
||||
}
|
||||
|
||||
this.tTemplate = null;
|
||||
ToolBase.destroyContext( ctx );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean setOptions( String... options )
|
||||
{
|
||||
if ( options.length != 1 ) {
|
||||
return false;
|
||||
}
|
||||
this.file = new File( options[ 0 ] );
|
||||
if ( ! ( this.file.isFile( ) && this.file.canRead( ) ) ) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,267 @@
|
|||
package com.deepclone.lw.cli;
|
||||
|
||||
|
||||
import java.io.*;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.AbstractApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.context.support.FileSystemXmlApplicationContext;
|
||||
import org.springframework.jdbc.core.SqlParameter;
|
||||
import org.springframework.jdbc.core.simple.SimpleJdbcCall;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.support.TransactionCallback;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
import com.thoughtworks.xstream.XStream;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
|
||||
import com.thoughtworks.xstream.annotations.XStreamImplicit;
|
||||
|
||||
|
||||
|
||||
public class ImportText
|
||||
extends CLITool
|
||||
{
|
||||
|
||||
private final Logger logger = Logger.getLogger( ImportText.class );
|
||||
|
||||
@SuppressWarnings( "serial" )
|
||||
public abstract static class StringData
|
||||
implements Serializable
|
||||
{
|
||||
@XStreamAsAttribute
|
||||
public String id;
|
||||
|
||||
|
||||
public abstract String getString( );
|
||||
}
|
||||
|
||||
@SuppressWarnings( "serial" )
|
||||
@XStreamAlias( "inline-string" )
|
||||
public static class InlineString
|
||||
extends StringData
|
||||
{
|
||||
public String value;
|
||||
|
||||
|
||||
@Override
|
||||
public String getString( )
|
||||
{
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings( "serial" )
|
||||
@XStreamAlias( "from-file" )
|
||||
public static class FileString
|
||||
extends StringData
|
||||
{
|
||||
@XStreamAsAttribute
|
||||
public String source;
|
||||
|
||||
|
||||
@Override
|
||||
public String getString( )
|
||||
{
|
||||
StringBuilder sBuilder = new StringBuilder( );
|
||||
try {
|
||||
BufferedReader in = new BufferedReader( new FileReader( source ) );
|
||||
String str;
|
||||
while ( ( str = in.readLine( ) ) != null ) {
|
||||
sBuilder.append( str );
|
||||
sBuilder.append( "\n" );
|
||||
}
|
||||
in.close( );
|
||||
} catch ( IOException e ) {
|
||||
throw new RuntimeException( "Could not read " + source );
|
||||
}
|
||||
|
||||
return sBuilder.toString( );
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings( "serial" )
|
||||
public static class LanguageData
|
||||
implements Serializable
|
||||
{
|
||||
@XStreamAsAttribute
|
||||
public String id;
|
||||
|
||||
@XStreamAsAttribute
|
||||
public String name;
|
||||
|
||||
@XStreamImplicit
|
||||
public List< StringData > strings = new LinkedList< StringData >( );
|
||||
}
|
||||
|
||||
@SuppressWarnings( "serial" )
|
||||
@XStreamAlias( "lw-text-data" )
|
||||
public static class TextData
|
||||
implements Serializable
|
||||
{
|
||||
@XStreamImplicit( itemFieldName = "language" )
|
||||
public List< LanguageData > languages = new LinkedList< LanguageData >( );
|
||||
}
|
||||
|
||||
private File file;
|
||||
private TransactionTemplate tTemplate;
|
||||
private SimpleJdbcCall uocTranslation;
|
||||
private SimpleJdbcCall uocLanguage;
|
||||
|
||||
|
||||
private XStream initXStream( )
|
||||
{
|
||||
XStream xstream = new XStream( );
|
||||
xstream.processAnnotations( TextData.class );
|
||||
xstream.processAnnotations( InlineString.class );
|
||||
xstream.processAnnotations( FileString.class );
|
||||
return xstream;
|
||||
}
|
||||
|
||||
|
||||
private TextData loadData( )
|
||||
{
|
||||
FileInputStream fis;
|
||||
try {
|
||||
fis = new FileInputStream( this.file );
|
||||
} catch ( FileNotFoundException e ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
XStream xstream = this.initXStream( );
|
||||
return (TextData) xstream.fromXML( fis );
|
||||
} catch ( Exception e ) {
|
||||
e.printStackTrace( );
|
||||
return null;
|
||||
} finally {
|
||||
try {
|
||||
fis.close( );
|
||||
} catch ( IOException e ) {
|
||||
// EMPTY
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private ClassPathXmlApplicationContext createContext( )
|
||||
{
|
||||
// Load data source and Hibernate properties
|
||||
String[] dataConfig = {
|
||||
this.getDataSource( ) ,
|
||||
};
|
||||
FileSystemXmlApplicationContext ctx = new FileSystemXmlApplicationContext( dataConfig );
|
||||
ctx.refresh( );
|
||||
|
||||
// Load transaction manager bean
|
||||
String[] cfg = {
|
||||
"configuration/transaction-bean.xml"
|
||||
};
|
||||
return new ClassPathXmlApplicationContext( cfg , true , ctx );
|
||||
}
|
||||
|
||||
|
||||
private void createTemplates( ApplicationContext ctx )
|
||||
{
|
||||
DataSource dSource = ctx.getBean( DataSource.class );
|
||||
PlatformTransactionManager tManager = ctx.getBean( PlatformTransactionManager.class );
|
||||
|
||||
this.uocLanguage = new SimpleJdbcCall( dSource ).withCatalogName( "defs" ).withProcedureName( "uoc_language" );
|
||||
this.uocLanguage.withoutProcedureColumnMetaDataAccess( );
|
||||
this.uocLanguage.declareParameters( new SqlParameter( "lid" , java.sql.Types.VARCHAR ) , new SqlParameter(
|
||||
"lname" , java.sql.Types.VARCHAR ) );
|
||||
|
||||
this.uocTranslation = new SimpleJdbcCall( dSource ).withCatalogName( "defs" ).withProcedureName(
|
||||
"uoc_translation" );
|
||||
this.uocTranslation.withoutProcedureColumnMetaDataAccess( );
|
||||
this.uocTranslation.declareParameters( new SqlParameter( "lid" , java.sql.Types.VARCHAR ) , new SqlParameter(
|
||||
"sid" , java.sql.Types.VARCHAR ) , new SqlParameter( "trans" , java.sql.Types.VARCHAR ) );
|
||||
|
||||
this.tTemplate = new TransactionTemplate( tManager );
|
||||
}
|
||||
|
||||
|
||||
private void importText( TextData data )
|
||||
{
|
||||
for ( LanguageData ld : data.languages ) {
|
||||
this.importLanguage( ld );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void importLanguage( LanguageData ld )
|
||||
{
|
||||
if ( ld.strings == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Try creating or updating the language
|
||||
this.uocLanguage.execute( ld.id , ld.name );
|
||||
|
||||
// Import translations
|
||||
for ( StringData sd : ld.strings ) {
|
||||
this.uocTranslation.execute( ld.id , sd.id , sd.getString( ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void run( )
|
||||
{
|
||||
final TextData data = this.loadData( );
|
||||
if ( data == null ) {
|
||||
System.err.println( "could not read data" );
|
||||
return;
|
||||
}
|
||||
|
||||
AbstractApplicationContext ctx = this.createContext( );
|
||||
this.createTemplates( ctx );
|
||||
boolean rv = this.tTemplate.execute( new TransactionCallback< Boolean >( ) {
|
||||
|
||||
@Override
|
||||
public Boolean doInTransaction( TransactionStatus status )
|
||||
{
|
||||
boolean rv;
|
||||
try {
|
||||
importText( data );
|
||||
rv = true;
|
||||
} catch ( RuntimeException e ) {
|
||||
logger.error( "Caught runtime exception" , e );
|
||||
rv = false;
|
||||
}
|
||||
if ( !rv ) {
|
||||
status.setRollbackOnly( );
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
if ( rv ) {
|
||||
this.logger.info( "Text import successful" );
|
||||
}
|
||||
|
||||
ToolBase.destroyContext( ctx );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean setOptions( String... options )
|
||||
{
|
||||
if ( options.length != 1 ) {
|
||||
return false;
|
||||
}
|
||||
this.file = new File( options[ 0 ] );
|
||||
if ( ! ( this.file.isFile( ) && this.file.canRead( ) ) ) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package com.deepclone.lw.cli;
|
||||
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
import com.deepclone.lw.srv.ServerTerminator;
|
||||
|
||||
|
||||
|
||||
public final class Stop
|
||||
extends CLITool
|
||||
{
|
||||
|
||||
private ApplicationContext getContext( )
|
||||
{
|
||||
Map< String , String > rmiTerminator = new HashMap< String , String >( );
|
||||
rmiTerminator.put( "termSrv" , "com.deepclone.lw.srv.ServerTerminator" );
|
||||
|
||||
return this.createClientContext( rmiTerminator );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void run( )
|
||||
{
|
||||
ApplicationContext ctx = this.getContext( );
|
||||
ServerTerminator terminator;
|
||||
try {
|
||||
terminator = (ServerTerminator) ctx.getBean( "termSrv" );
|
||||
} catch ( BeanCreationException e ) {
|
||||
System.err.println("Could not connect to server");
|
||||
return;
|
||||
}
|
||||
terminator.terminate( );
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
package com.deepclone.lw.cli;
|
||||
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.context.support.AbstractApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.context.support.FileSystemXmlApplicationContext;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
|
||||
import com.deepclone.lw.interfaces.sys.Ticker;
|
||||
import com.deepclone.lw.interfaces.sys.Ticker.Frequency;
|
||||
|
||||
|
||||
|
||||
public class Tick
|
||||
extends CLITool
|
||||
{
|
||||
|
||||
public static class FakeTickerBean
|
||||
implements Ticker
|
||||
{
|
||||
Map< Frequency , List< Runnable > > tasks = new HashMap< Frequency , List< Runnable > >( );
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isActive( )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void pause( )
|
||||
throws IllegalStateException
|
||||
{
|
||||
// EMPTY
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
synchronized public void registerTask( Frequency frequency , String name , Runnable task )
|
||||
{
|
||||
List< Runnable > tasks = this.tasks.get( frequency );
|
||||
if ( tasks == null ) {
|
||||
tasks = new LinkedList< Runnable >( );
|
||||
this.tasks.put( frequency , tasks );
|
||||
}
|
||||
tasks.add( task );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void unpause( )
|
||||
throws IllegalStateException
|
||||
{
|
||||
// EMPTY
|
||||
}
|
||||
|
||||
|
||||
public void runFrequency( Frequency frequency )
|
||||
{
|
||||
List< Runnable > tasks = this.tasks.get( frequency );
|
||||
if ( tasks == null ) {
|
||||
return;
|
||||
}
|
||||
for ( Runnable r : tasks ) {
|
||||
r.run( );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private AbstractApplicationContext getContext( )
|
||||
{
|
||||
// Load data source and Hibernate properties
|
||||
String[] dataConfig = {
|
||||
this.getDataSource( ) ,
|
||||
};
|
||||
FileSystemXmlApplicationContext ctx = new FileSystemXmlApplicationContext( dataConfig );
|
||||
ctx.refresh( );
|
||||
|
||||
// Load fake ticker
|
||||
GenericApplicationContext gac = new GenericApplicationContext( ctx );
|
||||
gac.registerBeanDefinition( "fakeTicker" , BeanDefinitionBuilder.rootBeanDefinition( FakeTickerBean.class )
|
||||
.getBeanDefinition( ) );
|
||||
gac.refresh( );
|
||||
|
||||
String[] cfg = {
|
||||
"configuration/context-configuration.xml" , "configuration/transaction-bean.xml" ,
|
||||
"configuration/accounts-beans.xml" , "configuration/bt-beans.xml" , "configuration/eventlog-beans.xml" ,
|
||||
"configuration/i18n-beans.xml" , "configuration/mailer-beans.xml" , "configuration/naming-beans.xml" ,
|
||||
"configuration/simple-beans.xml" ,
|
||||
"configuration/system/constants-manager-bean.xml" , "configuration/system/system-status-bean.xml"
|
||||
};
|
||||
return new ClassPathXmlApplicationContext( cfg , true , gac );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void run( )
|
||||
{
|
||||
AbstractApplicationContext ctx = this.getContext( );
|
||||
FakeTickerBean ftb = ctx.getBean( FakeTickerBean.class );
|
||||
ftb.runFrequency( Frequency.MINUTE );
|
||||
ToolBase.destroyContext( ctx );
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
package com.deepclone.lw.cli;
|
||||
|
||||
|
||||
import org.springframework.context.support.AbstractApplicationContext;
|
||||
|
||||
|
||||
|
||||
public abstract class ToolBase
|
||||
implements Runnable
|
||||
{
|
||||
|
||||
private String dataSource;
|
||||
private int rmiPort;
|
||||
private int servPort;
|
||||
|
||||
|
||||
protected final String getDataSource( )
|
||||
{
|
||||
return this.dataSource;
|
||||
}
|
||||
|
||||
|
||||
protected final int getRmiPort( )
|
||||
{
|
||||
return this.rmiPort;
|
||||
}
|
||||
|
||||
|
||||
protected final int getServicePort( )
|
||||
{
|
||||
return this.servPort;
|
||||
}
|
||||
|
||||
|
||||
protected final int getTerminationPort( )
|
||||
{
|
||||
return this.servPort + 1;
|
||||
}
|
||||
|
||||
|
||||
protected static void destroyContext( AbstractApplicationContext aac )
|
||||
{
|
||||
while ( aac != null ) {
|
||||
AbstractApplicationContext p = (AbstractApplicationContext) aac.getParent( );
|
||||
aac.destroy( );
|
||||
aac = p;
|
||||
}
|
||||
System.gc( );
|
||||
try {
|
||||
Thread.sleep( 1000L );
|
||||
} catch ( InterruptedException e ) {
|
||||
e.printStackTrace( );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public final void setMainSettings( String dataSource , int rmiPort , int servPort )
|
||||
{
|
||||
this.dataSource = dataSource;
|
||||
this.rmiPort = rmiPort;
|
||||
this.servPort = servPort;
|
||||
}
|
||||
|
||||
|
||||
public boolean setOptions( String... options )
|
||||
{
|
||||
return ( options == null || options.length == 0 );
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package com.deepclone.lw.cli.dbexport;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
|
||||
|
||||
|
||||
|
||||
@SuppressWarnings( "serial" )
|
||||
@XStreamAlias( "administrator" )
|
||||
public class Administrator
|
||||
implements Serializable
|
||||
{
|
||||
|
||||
@XStreamAsAttribute
|
||||
public int id;
|
||||
|
||||
@XStreamAsAttribute
|
||||
public String name;
|
||||
|
||||
@XStreamAsAttribute
|
||||
public int privileges;
|
||||
|
||||
public String md5;
|
||||
public String sha1;
|
||||
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package com.deepclone.lw.cli.dbexport;
|
||||
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
|
||||
|
||||
|
||||
|
||||
@SuppressWarnings( "serial" )
|
||||
@XStreamAlias( "comment" )
|
||||
public class BREComment
|
||||
extends BugReportEvent
|
||||
{
|
||||
|
||||
@XStreamAsAttribute
|
||||
public boolean visible;
|
||||
|
||||
public String text;
|
||||
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package com.deepclone.lw.cli.dbexport;
|
||||
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
|
||||
|
||||
|
||||
|
||||
@SuppressWarnings( "serial" )
|
||||
@XStreamAlias( "initial-report" )
|
||||
public class BREInitialReport
|
||||
extends BugReportEvent
|
||||
{
|
||||
|
||||
@XStreamAsAttribute
|
||||
public String title;
|
||||
|
||||
public String contents;
|
||||
|
||||
public String xmlData;
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package com.deepclone.lw.cli.dbexport;
|
||||
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
|
||||
|
||||
|
||||
|
||||
@SuppressWarnings( "serial" )
|
||||
@XStreamAlias( "merge-reports" )
|
||||
public class BREMerger
|
||||
extends BugReportEvent
|
||||
{
|
||||
|
||||
@XStreamAsAttribute
|
||||
@XStreamAlias( "from-report" )
|
||||
public long merged;
|
||||
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package com.deepclone.lw.cli.dbexport;
|
||||
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
|
||||
|
||||
|
||||
|
||||
@SuppressWarnings( "serial" )
|
||||
@XStreamAlias( "status-change" )
|
||||
public class BREStatusChange
|
||||
extends BugReportEvent
|
||||
{
|
||||
|
||||
@XStreamAsAttribute
|
||||
public String status;
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package com.deepclone.lw.cli.dbexport;
|
||||
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
|
||||
|
||||
@SuppressWarnings( "serial" )
|
||||
@XStreamAlias( "visibility-change" )
|
||||
public class BREVisibilityChange
|
||||
extends BugReportEvent
|
||||
{
|
||||
|
||||
public boolean visible;
|
||||
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
package com.deepclone.lw.cli.dbexport;
|
||||
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
|
||||
import com.deepclone.lw.cmd.bt.data.BugEventType;
|
||||
|
||||
|
||||
|
||||
public class BugEventMapper
|
||||
implements RowMapper< BugReportEvent >
|
||||
{
|
||||
|
||||
@Override
|
||||
public BugReportEvent mapRow( ResultSet rs , int rowNum )
|
||||
throws SQLException
|
||||
{
|
||||
BugEventType bet = BugEventType.valueOf( rs.getString( "event_type" ) );
|
||||
BugReportEvent bre;
|
||||
|
||||
switch ( bet ) {
|
||||
case COMMENT:
|
||||
bre = this.getComment( rs );
|
||||
break;
|
||||
case INIT:
|
||||
bre = this.getInitialReport( rs );
|
||||
break;
|
||||
case MERGE:
|
||||
bre = this.getMerger( rs );
|
||||
break;
|
||||
case STATUS:
|
||||
bre = this.getStatusChange( rs );
|
||||
break;
|
||||
case VISIBILITY:
|
||||
bre = this.getVisibility( rs );
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException( bet.toString( ) );
|
||||
}
|
||||
|
||||
bre.id = rs.getLong( "event_id" );
|
||||
bre.timestamp = rs.getTimestamp( "event_timestamp" );
|
||||
bre.submitter = this.getSubmitter( rs );
|
||||
|
||||
return bre;
|
||||
}
|
||||
|
||||
|
||||
private BugSubmitter getSubmitter( ResultSet rs )
|
||||
throws SQLException
|
||||
{
|
||||
BugSubmitter submitter = new BugSubmitter( );
|
||||
submitter.isAdmin = rs.getBoolean( "submitter_admin" );
|
||||
submitter.name = rs.getString( "submitter_name" );
|
||||
return submitter;
|
||||
}
|
||||
|
||||
|
||||
private BugReportEvent getComment( ResultSet rs )
|
||||
throws SQLException
|
||||
{
|
||||
BREComment evt = new BREComment( );
|
||||
evt.text = rs.getString( "contents" );
|
||||
evt.visible = rs.getBoolean( "visible" );
|
||||
return evt;
|
||||
}
|
||||
|
||||
|
||||
private BugReportEvent getInitialReport( ResultSet rs )
|
||||
throws SQLException
|
||||
{
|
||||
BREInitialReport evt = new BREInitialReport( );
|
||||
evt.title = rs.getString( "title" );
|
||||
evt.contents = rs.getString( "contents" );
|
||||
evt.xmlData = rs.getString( "account_status" );
|
||||
return evt;
|
||||
}
|
||||
|
||||
|
||||
private BugReportEvent getMerger( ResultSet rs )
|
||||
throws SQLException
|
||||
{
|
||||
BREMerger evt = new BREMerger( );
|
||||
evt.merged = rs.getLong( "merged_report_id" );
|
||||
return evt;
|
||||
}
|
||||
|
||||
|
||||
private BugReportEvent getStatusChange( ResultSet rs )
|
||||
throws SQLException
|
||||
{
|
||||
BREStatusChange evt = new BREStatusChange( );
|
||||
evt.status = rs.getString( "status" );
|
||||
return evt;
|
||||
}
|
||||
|
||||
|
||||
private BugReportEvent getVisibility( ResultSet rs )
|
||||
throws SQLException
|
||||
{
|
||||
BREVisibilityChange evt = new BREVisibilityChange( );
|
||||
evt.visible = rs.getBoolean( "visible" );
|
||||
return evt;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package com.deepclone.lw.cli.dbexport;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
import com.thoughtworks.xstream.annotations.XStreamImplicit;
|
||||
|
||||
|
||||
|
||||
@SuppressWarnings( "serial" )
|
||||
@XStreamAlias( "bug-group" )
|
||||
public class BugGroup
|
||||
implements Serializable
|
||||
{
|
||||
|
||||
@XStreamImplicit( itemFieldName = "event-id" )
|
||||
public List< Long > events = new ArrayList< Long >( );
|
||||
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package com.deepclone.lw.cli.dbexport;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.sql.Timestamp;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
|
||||
|
||||
|
||||
|
||||
@SuppressWarnings( "serial" )
|
||||
public abstract class BugReportEvent
|
||||
implements Serializable
|
||||
{
|
||||
|
||||
@XStreamAsAttribute
|
||||
public long id;
|
||||
|
||||
@XStreamAsAttribute
|
||||
public Timestamp timestamp;
|
||||
|
||||
public BugSubmitter submitter;
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package com.deepclone.lw.cli.dbexport;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
|
||||
@SuppressWarnings( "serial" )
|
||||
public class BugReports
|
||||
implements Serializable
|
||||
{
|
||||
|
||||
public List< BugGroup > groups;
|
||||
|
||||
public List< BugReportEvent > events;
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package com.deepclone.lw.cli.dbexport;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
|
||||
|
||||
|
||||
|
||||
@SuppressWarnings( "serial" )
|
||||
@XStreamAlias( "submitter" )
|
||||
public class BugSubmitter
|
||||
implements Serializable
|
||||
{
|
||||
|
||||
@XStreamAsAttribute
|
||||
public String name;
|
||||
|
||||
@XStreamAlias( "is-admin" )
|
||||
@XStreamAsAttribute
|
||||
public boolean isAdmin;
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package com.deepclone.lw.cli.dbexport;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
|
||||
|
||||
|
||||
|
||||
@SuppressWarnings( "serial" )
|
||||
@XStreamAlias( "legacyworlds" )
|
||||
public class LegacyWorldsDB
|
||||
implements Serializable
|
||||
{
|
||||
|
||||
@XStreamAsAttribute
|
||||
public int version = 1;
|
||||
|
||||
public List< User > users;
|
||||
|
||||
@XStreamAlias( "bug-reports" )
|
||||
public BugReports bugReports = new BugReports( );
|
||||
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package com.deepclone.lw.cli.dbexport;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
|
||||
|
||||
|
||||
|
||||
@SuppressWarnings( "serial" )
|
||||
@XStreamAlias( "user" )
|
||||
public class User
|
||||
implements Serializable
|
||||
{
|
||||
|
||||
@XStreamAsAttribute
|
||||
public String address;
|
||||
|
||||
@XStreamAsAttribute
|
||||
public String language;
|
||||
|
||||
@XStreamAsAttribute
|
||||
@XStreamAlias( "game-credits" )
|
||||
public int gameCredits;
|
||||
|
||||
@XStreamAsAttribute
|
||||
@XStreamAlias("vacation-credits")
|
||||
public int vacationCredits;
|
||||
|
||||
public String md5;
|
||||
public String sha1;
|
||||
|
||||
public String empire;
|
||||
|
||||
public Warnings warnings;
|
||||
public Administrator administrator;
|
||||
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
package com.deepclone.lw.cli.dbexport;
|
||||
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
|
||||
|
||||
|
||||
public class UserMapper
|
||||
implements RowMapper< User >
|
||||
{
|
||||
|
||||
@Override
|
||||
public User mapRow( ResultSet rs , int rowNum )
|
||||
throws SQLException
|
||||
{
|
||||
User user = new User( );
|
||||
|
||||
user.address = rs.getString( "address" );
|
||||
user.language = rs.getString( "language" );
|
||||
user.gameCredits = rs.getInt( "game_credits" );
|
||||
user.vacationCredits = rs.getInt( "vacation_credits" );
|
||||
user.md5 = rs.getString( "pass_md5" );
|
||||
user.sha1 = rs.getString( "pass_sha1" );
|
||||
user.empire = rs.getString( "current_empire" );
|
||||
|
||||
int wCount = rs.getInt( "warnings_count" );
|
||||
if ( wCount > 0 ) {
|
||||
user.warnings = new Warnings( );
|
||||
user.warnings.count = wCount;
|
||||
user.warnings.last = rs.getTimestamp( "warnings_last" );
|
||||
}
|
||||
|
||||
String aName = rs.getString( "administrator_name" );
|
||||
if ( aName != null ) {
|
||||
user.administrator = new Administrator( );
|
||||
user.administrator.id = rs.getInt( "administrator_id" );
|
||||
user.administrator.name = aName;
|
||||
user.administrator.privileges = rs.getInt( "privileges" );
|
||||
user.administrator.md5 = rs.getString( "administrator_md5" );
|
||||
user.administrator.sha1 = rs.getString( "administrator_sha1" );
|
||||
}
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package com.deepclone.lw.cli.dbexport;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.sql.Timestamp;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
|
||||
|
||||
|
||||
|
||||
@SuppressWarnings( "serial" )
|
||||
@XStreamAlias( "warnings" )
|
||||
public class Warnings
|
||||
implements Serializable
|
||||
{
|
||||
|
||||
@XStreamAsAttribute
|
||||
public int count;
|
||||
|
||||
@XStreamAsAttribute
|
||||
public Timestamp last;
|
||||
}
|
|
@ -0,0 +1,513 @@
|
|||
package com.deepclone.lw.srv;
|
||||
|
||||
|
||||
/**
|
||||
* Adapted from the Apache Log4j DailyRollingFileAppender to extend the functionality of the
|
||||
* existing class so that the user can limit the number of log backups and compress the backups to
|
||||
* conserve disk space.
|
||||
*
|
||||
* @author Ryan Kimber
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file to You under the Apache
|
||||
* License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the
|
||||
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
|
||||
import java.io.FileFilter;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.File;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.Calendar;
|
||||
import java.util.TimeZone;
|
||||
import java.util.Locale;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
// We have to import the log4j package because this class used to be in it and references other
|
||||
// classes in that package.
|
||||
import org.apache.log4j.*;
|
||||
import org.apache.log4j.helpers.LogLog;
|
||||
import org.apache.log4j.spi.LoggingEvent;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* CustodianDailyRollingFileAppender is based on
|
||||
* {@link org.apache.log4j.appender.DailyRollingFileAppender} so most of the configuration options
|
||||
* can be taken from the documentation on that class.
|
||||
*/
|
||||
public class LogAppender
|
||||
extends FileAppender
|
||||
{
|
||||
// The code assumes that the following constants are in a increasing
|
||||
// sequence.
|
||||
static final int TOP_OF_TROUBLE = -1;
|
||||
static final int TOP_OF_MINUTE = 0;
|
||||
static final int TOP_OF_HOUR = 1;
|
||||
static final int HALF_DAY = 2;
|
||||
static final int TOP_OF_DAY = 3;
|
||||
static final int TOP_OF_WEEK = 4;
|
||||
static final int TOP_OF_MONTH = 5;
|
||||
|
||||
/**
|
||||
* The date pattern. By default, the pattern is set to "'.'yyyy-MM-dd" meaning daily rollover.
|
||||
*/
|
||||
private String datePattern = "'.'yyyy-MM-dd";
|
||||
private String compressBackups = "false";
|
||||
private String maxNumberOfDays = "7";
|
||||
|
||||
/**
|
||||
* The log file will be renamed to the value of the scheduledFilename variable when the next
|
||||
* interval is entered. For example, if the rollover period is one hour, the log file will be
|
||||
* renamed to the value of "scheduledFilename" at the beginning of the next hour.
|
||||
*
|
||||
* The precise time when a rollover occurs depends on logging activity.
|
||||
*/
|
||||
private String scheduledFilename;
|
||||
|
||||
/**
|
||||
* The next time we estimate a rollover should occur.
|
||||
*/
|
||||
private long nextCheck = System.currentTimeMillis( ) - 1;
|
||||
|
||||
Date now = new Date( );
|
||||
|
||||
SimpleDateFormat sdf;
|
||||
|
||||
RollingCalendar rc = new RollingCalendar( );
|
||||
|
||||
int checkPeriod = TOP_OF_TROUBLE;
|
||||
|
||||
// The gmtTimeZone is used only in computeCheckPeriod() method.
|
||||
static final TimeZone gmtTimeZone = TimeZone.getTimeZone( "GMT" );
|
||||
|
||||
|
||||
/**
|
||||
* The default constructor does nothing.
|
||||
*/
|
||||
public LogAppender( )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Instantiate a LogAppender and open the file designated by filename. The opened filename will
|
||||
* become the ouput destination for this appender.
|
||||
*/
|
||||
public LogAppender( Layout layout , String filename , String datePattern )
|
||||
throws IOException
|
||||
{
|
||||
super( layout , filename , true );
|
||||
this.datePattern = datePattern;
|
||||
activateOptions( );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The DatePattern takes a string in the same format as expected by {@link SimpleDateFormat}.
|
||||
* This options determines the rollover schedule.
|
||||
*/
|
||||
public void setDatePattern( String pattern )
|
||||
{
|
||||
datePattern = pattern;
|
||||
}
|
||||
|
||||
|
||||
/** Returns the value of the DatePattern option. */
|
||||
public String getDatePattern( )
|
||||
{
|
||||
return datePattern;
|
||||
}
|
||||
|
||||
|
||||
public void activateOptions( )
|
||||
{
|
||||
super.activateOptions( );
|
||||
if ( datePattern != null && fileName != null ) {
|
||||
now.setTime( System.currentTimeMillis( ) );
|
||||
sdf = new SimpleDateFormat( datePattern );
|
||||
int type = computeCheckPeriod( );
|
||||
printPeriodicity( type );
|
||||
rc.setType( type );
|
||||
File file = new File( fileName );
|
||||
scheduledFilename = fileName + sdf.format( new Date( file.lastModified( ) ) );
|
||||
|
||||
} else {
|
||||
LogLog.error( "Either File or DatePattern options are not set for appender [" + name + "]." );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void printPeriodicity( int type )
|
||||
{
|
||||
switch ( type ) {
|
||||
case TOP_OF_MINUTE:
|
||||
LogLog.debug( "Appender [" + name + "] to be rolled every minute." );
|
||||
break;
|
||||
case TOP_OF_HOUR:
|
||||
LogLog.debug( "Appender [" + name + "] to be rolled on top of every hour." );
|
||||
break;
|
||||
case HALF_DAY:
|
||||
LogLog.debug( "Appender [" + name + "] to be rolled at midday and midnight." );
|
||||
break;
|
||||
case TOP_OF_DAY:
|
||||
LogLog.debug( "Appender [" + name + "] to be rolled at midnight." );
|
||||
break;
|
||||
case TOP_OF_WEEK:
|
||||
LogLog.debug( "Appender [" + name + "] to be rolled at start of week." );
|
||||
break;
|
||||
case TOP_OF_MONTH:
|
||||
LogLog.debug( "Appender [" + name + "] to be rolled at start of every month." );
|
||||
break;
|
||||
default:
|
||||
LogLog.warn( "Unknown periodicity for appender [" + name + "]." );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// This method computes the roll over period by looping over the
|
||||
// periods, starting with the shortest, and stopping when the r0 is
|
||||
// different from from r1, where r0 is the epoch formatted according
|
||||
// the datePattern (supplied by the user) and r1 is the
|
||||
// epoch+nextMillis(i) formatted according to datePattern. All date
|
||||
// formatting is done in GMT and not local format because the test
|
||||
// logic is based on comparisons relative to 1970-01-01 00:00:00
|
||||
// GMT (the epoch).
|
||||
|
||||
int computeCheckPeriod( )
|
||||
{
|
||||
RollingCalendar rollingCalendar = new RollingCalendar( gmtTimeZone , Locale.ENGLISH );
|
||||
// set sate to 1970-01-01 00:00:00 GMT
|
||||
Date epoch = new Date( 0 );
|
||||
if ( datePattern != null ) {
|
||||
for ( int i = TOP_OF_MINUTE ; i <= TOP_OF_MONTH ; i++ ) {
|
||||
SimpleDateFormat simpleDateFormat = new SimpleDateFormat( datePattern );
|
||||
simpleDateFormat.setTimeZone( gmtTimeZone ); // do all date
|
||||
// formatting in GMT
|
||||
String r0 = simpleDateFormat.format( epoch );
|
||||
rollingCalendar.setType( i );
|
||||
Date next = new Date( rollingCalendar.getNextCheckMillis( epoch ) );
|
||||
String r1 = simpleDateFormat.format( next );
|
||||
// System.out.println("Type = "+i+", r0 = "+r0+", r1 = "+r1);
|
||||
if ( r0 != null && r1 != null && !r0.equals( r1 ) ) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return TOP_OF_TROUBLE; // Deliberately head for trouble...
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Rollover the current file to a new file.
|
||||
*/
|
||||
void rollOver( )
|
||||
throws IOException
|
||||
{
|
||||
|
||||
/* Compute filename, but only if datePattern is specified */
|
||||
if ( datePattern == null ) {
|
||||
errorHandler.error( "Missing DatePattern option in rollOver()." );
|
||||
return;
|
||||
}
|
||||
|
||||
String datedFilename = fileName + sdf.format( now );
|
||||
// It is too early to roll over because we are still within the
|
||||
// bounds of the current interval. Rollover will occur once the
|
||||
// next interval is reached.
|
||||
if ( scheduledFilename.equals( datedFilename ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// close current file, and rename it to datedFilename
|
||||
this.closeFile( );
|
||||
|
||||
File target = new File( scheduledFilename );
|
||||
if ( target.exists( ) ) {
|
||||
target.delete( );
|
||||
}
|
||||
|
||||
File file = new File( fileName );
|
||||
boolean result = file.renameTo( target );
|
||||
if ( result ) {
|
||||
LogLog.debug( fileName + " -> " + scheduledFilename );
|
||||
} else {
|
||||
LogLog.error( "Failed to rename [" + fileName + "] to [" + scheduledFilename + "]." );
|
||||
}
|
||||
|
||||
try {
|
||||
// This will also close the file. This is OK since multiple
|
||||
// close operations are safe.
|
||||
this.setFile( fileName , false , this.bufferedIO , this.bufferSize );
|
||||
} catch ( IOException e ) {
|
||||
errorHandler.error( "setFile(" + fileName + ", false) call failed." );
|
||||
}
|
||||
scheduledFilename = datedFilename;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method differentiates DailyRollingFileAppender from its super class.
|
||||
*
|
||||
*
|
||||
* Before actually logging, this method will check whether it is time to do a rollover. If it
|
||||
* is, it will schedule the next rollover time and then rollover.
|
||||
* */
|
||||
protected void subAppend( LoggingEvent event )
|
||||
{
|
||||
long n = System.currentTimeMillis( );
|
||||
if ( n >= nextCheck ) {
|
||||
now.setTime( n );
|
||||
nextCheck = rc.getNextCheckMillis( now );
|
||||
try {
|
||||
cleanupAndRollOver( );
|
||||
} catch ( IOException ioe ) {
|
||||
LogLog.error( "cleanupAndRollover() failed." , ioe );
|
||||
}
|
||||
}
|
||||
super.subAppend( event );
|
||||
}
|
||||
|
||||
|
||||
public String getCompressBackups( )
|
||||
{
|
||||
return compressBackups;
|
||||
}
|
||||
|
||||
|
||||
public void setCompressBackups( String compressBackups )
|
||||
{
|
||||
this.compressBackups = compressBackups;
|
||||
}
|
||||
|
||||
|
||||
public String getMaxNumberOfDays( )
|
||||
{
|
||||
return maxNumberOfDays;
|
||||
}
|
||||
|
||||
|
||||
public void setMaxNumberOfDays( String maxNumberOfDays )
|
||||
{
|
||||
this.maxNumberOfDays = maxNumberOfDays;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This method checks to see if we're exceeding the number of log backups that we are supposed
|
||||
* to keep, and if so, deletes the offending files. It then delegates to the rollover method to
|
||||
* rollover to a new file if required.
|
||||
*/
|
||||
protected void cleanupAndRollOver( )
|
||||
throws IOException
|
||||
{
|
||||
// Check to see if there are already 5 files
|
||||
File file = new File( fileName );
|
||||
Calendar cal = Calendar.getInstance( );
|
||||
int maxDays = 7;
|
||||
try {
|
||||
maxDays = Integer.parseInt( getMaxNumberOfDays( ) );
|
||||
} catch ( Exception e ) {
|
||||
// just leave it at 7.
|
||||
}
|
||||
cal.add( Calendar.DATE , -maxDays );
|
||||
Date cutoffDate = cal.getTime( );
|
||||
if ( file.getParentFile( ).exists( ) ) {
|
||||
File[] files = file.getParentFile( ).listFiles( new StartsWithFileFilter( file.getName( ) , false ) );
|
||||
int nameLength = file.getName( ).length( );
|
||||
for ( int i = 0 ; i < files.length ; i++ ) {
|
||||
String datePart = null;
|
||||
try {
|
||||
datePart = files[ i ].getName( ).substring( nameLength );
|
||||
Date date = sdf.parse( datePart );
|
||||
if ( date.before( cutoffDate ) ) {
|
||||
files[ i ].delete( );
|
||||
}
|
||||
// If we're supposed to zip files and this isn't already a zip
|
||||
else if ( getCompressBackups( ).equalsIgnoreCase( "YES" )
|
||||
|| getCompressBackups( ).equalsIgnoreCase( "TRUE" ) ) {
|
||||
zipAndDelete( files[ i ] );
|
||||
}
|
||||
} catch ( Exception pe ) {
|
||||
// This isn't a file we should touch (it isn't named
|
||||
// correctly)
|
||||
}
|
||||
}
|
||||
}
|
||||
rollOver( );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compresses the passed file to a .zip file, stores the .zip in the same directory as the
|
||||
* passed file, and then deletes the original, leaving only the .zipped archive.
|
||||
*
|
||||
* @param file
|
||||
*/
|
||||
private void zipAndDelete( File file )
|
||||
throws IOException
|
||||
{
|
||||
if ( !file.getName( ).endsWith( ".zip" ) ) {
|
||||
File zipFile = new File( file.getParent( ) , file.getName( ) + ".zip" );
|
||||
FileInputStream fis = new FileInputStream( file );
|
||||
FileOutputStream fos = new FileOutputStream( zipFile );
|
||||
ZipOutputStream zos = new ZipOutputStream( fos );
|
||||
ZipEntry zipEntry = new ZipEntry( file.getName( ) );
|
||||
zos.putNextEntry( zipEntry );
|
||||
|
||||
byte[] buffer = new byte[ 4096 ];
|
||||
while ( true ) {
|
||||
int bytesRead = fis.read( buffer );
|
||||
if ( bytesRead == -1 )
|
||||
break;
|
||||
else {
|
||||
zos.write( buffer , 0 , bytesRead );
|
||||
}
|
||||
}
|
||||
zos.closeEntry( );
|
||||
fis.close( );
|
||||
zos.close( );
|
||||
file.delete( );
|
||||
}
|
||||
}
|
||||
|
||||
class StartsWithFileFilter
|
||||
implements FileFilter
|
||||
{
|
||||
private String startsWith;
|
||||
private boolean inclDirs = false;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public StartsWithFileFilter( String startsWith , boolean includeDirectories )
|
||||
{
|
||||
super( );
|
||||
this.startsWith = startsWith.toUpperCase( );
|
||||
inclDirs = includeDirectories;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.io.FileFilter#accept(java.io.File)
|
||||
*/
|
||||
public boolean accept( File pathname )
|
||||
{
|
||||
if ( !inclDirs && pathname.isDirectory( ) ) {
|
||||
return false;
|
||||
} else
|
||||
return pathname.getName( ).toUpperCase( ).startsWith( startsWith );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* RollingCalendar is a helper class to DailyRollingFileAppender. Given a periodicity type and the
|
||||
* current time, it computes the start of the next interval.
|
||||
* */
|
||||
class RollingCalendar
|
||||
extends GregorianCalendar
|
||||
{
|
||||
private static final long serialVersionUID = -3560331770601814177L;
|
||||
|
||||
int type = LogAppender.TOP_OF_TROUBLE;
|
||||
|
||||
|
||||
RollingCalendar( )
|
||||
{
|
||||
super( );
|
||||
}
|
||||
|
||||
|
||||
RollingCalendar( TimeZone tz , Locale locale )
|
||||
{
|
||||
super( tz , locale );
|
||||
}
|
||||
|
||||
|
||||
void setType( int type )
|
||||
{
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
|
||||
public long getNextCheckMillis( Date now )
|
||||
{
|
||||
return getNextCheckDate( now ).getTime( );
|
||||
}
|
||||
|
||||
|
||||
public Date getNextCheckDate( Date now )
|
||||
{
|
||||
this.setTime( now );
|
||||
|
||||
switch ( type ) {
|
||||
case LogAppender.TOP_OF_MINUTE:
|
||||
this.set( Calendar.SECOND , 0 );
|
||||
this.set( Calendar.MILLISECOND , 0 );
|
||||
this.add( Calendar.MINUTE , 1 );
|
||||
break;
|
||||
case LogAppender.TOP_OF_HOUR:
|
||||
this.set( Calendar.MINUTE , 0 );
|
||||
this.set( Calendar.SECOND , 0 );
|
||||
this.set( Calendar.MILLISECOND , 0 );
|
||||
this.add( Calendar.HOUR_OF_DAY , 1 );
|
||||
break;
|
||||
case LogAppender.HALF_DAY:
|
||||
this.set( Calendar.MINUTE , 0 );
|
||||
this.set( Calendar.SECOND , 0 );
|
||||
this.set( Calendar.MILLISECOND , 0 );
|
||||
int hour = get( Calendar.HOUR_OF_DAY );
|
||||
if ( hour < 12 ) {
|
||||
this.set( Calendar.HOUR_OF_DAY , 12 );
|
||||
} else {
|
||||
this.set( Calendar.HOUR_OF_DAY , 0 );
|
||||
this.add( Calendar.DAY_OF_MONTH , 1 );
|
||||
}
|
||||
break;
|
||||
case LogAppender.TOP_OF_DAY:
|
||||
this.set( Calendar.HOUR_OF_DAY , 0 );
|
||||
this.set( Calendar.MINUTE , 0 );
|
||||
this.set( Calendar.SECOND , 0 );
|
||||
this.set( Calendar.MILLISECOND , 0 );
|
||||
this.add( Calendar.DATE , 1 );
|
||||
break;
|
||||
case LogAppender.TOP_OF_WEEK:
|
||||
this.set( Calendar.DAY_OF_WEEK , getFirstDayOfWeek( ) );
|
||||
this.set( Calendar.HOUR_OF_DAY , 0 );
|
||||
this.set( Calendar.MINUTE , 0 );
|
||||
this.set( Calendar.SECOND , 0 );
|
||||
this.set( Calendar.MILLISECOND , 0 );
|
||||
this.add( Calendar.WEEK_OF_YEAR , 1 );
|
||||
break;
|
||||
case LogAppender.TOP_OF_MONTH:
|
||||
this.set( Calendar.DATE , 1 );
|
||||
this.set( Calendar.HOUR_OF_DAY , 0 );
|
||||
this.set( Calendar.MINUTE , 0 );
|
||||
this.set( Calendar.SECOND , 0 );
|
||||
this.set( Calendar.MILLISECOND , 0 );
|
||||
this.add( Calendar.MONTH , 1 );
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException( "Unknown periodicity type." );
|
||||
}
|
||||
return getTime( );
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
package com.deepclone.lw.srv;
|
||||
|
||||
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.AbstractApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.context.support.FileSystemXmlApplicationContext;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
|
||||
import com.deepclone.lw.cli.ToolBase;
|
||||
import com.deepclone.lw.interfaces.session.SessionManager;
|
||||
|
||||
|
||||
|
||||
public class Server
|
||||
extends ToolBase
|
||||
{
|
||||
private static final String[] beanConfigurations = {
|
||||
"lw-server.xml" ,
|
||||
};
|
||||
|
||||
private Lock terminationLock = new ReentrantLock( );
|
||||
private Condition termination = this.terminationLock.newCondition( );
|
||||
|
||||
private AbstractApplicationContext applicationContext;
|
||||
|
||||
|
||||
private void addRMIService( GenericApplicationContext ctx , String name , Object bean , Class< ? > iface , int sPort )
|
||||
{
|
||||
BeanDefinitionBuilder builder;
|
||||
builder = BeanDefinitionBuilder.rootBeanDefinition( "org.springframework.remoting.rmi.RmiServiceExporter" );
|
||||
builder.setScope( BeanDefinition.SCOPE_SINGLETON );
|
||||
builder.addPropertyValue( "serviceName" , name );
|
||||
builder.addPropertyValue( "service" , bean );
|
||||
builder.addPropertyValue( "ServiceInterface" , iface.getCanonicalName( ) );
|
||||
builder.addPropertyValue( "registryPort" , String.valueOf( this.getRmiPort( ) ) );
|
||||
builder.addPropertyValue( "servicePort" , String.valueOf( sPort ) );
|
||||
ctx.registerBeanDefinition( name , builder.getBeanDefinition( ) );
|
||||
}
|
||||
|
||||
|
||||
private AbstractApplicationContext makeRMIContext( ApplicationContext parent )
|
||||
{
|
||||
GenericApplicationContext context = new GenericApplicationContext( parent );
|
||||
this.addRMIService( context , "termSrv" , parent.getBean( "terminator" ) , ServerTerminator.class , this.getTerminationPort( ) );
|
||||
this.addRMIService( context , "sessionSrv" , parent.getBean( "sessionManager" ) , SessionManager.class , this.getServicePort( ) );
|
||||
context.refresh( );
|
||||
return context;
|
||||
}
|
||||
|
||||
|
||||
private ApplicationContext makeDataConfigContext( )
|
||||
{
|
||||
String[] dSource = {
|
||||
this.getDataSource( ) ,
|
||||
};
|
||||
FileSystemXmlApplicationContext ctx = new FileSystemXmlApplicationContext( dSource );
|
||||
ctx.refresh( );
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
||||
private void createBeans( )
|
||||
{
|
||||
ApplicationContext ctx = this.makeDataConfigContext( );
|
||||
ctx = new ClassPathXmlApplicationContext( Server.beanConfigurations , true , ctx );
|
||||
this.applicationContext = this.makeRMIContext( ctx );
|
||||
}
|
||||
|
||||
|
||||
private void initialiseBeans( )
|
||||
{
|
||||
this.createBeans( );
|
||||
this.applicationContext.getBean( "terminator" , ServerTerminatorBean.class ).setServer( this );
|
||||
}
|
||||
|
||||
|
||||
private void waitForTermination( )
|
||||
{
|
||||
this.terminationLock.lock( );
|
||||
this.termination.awaitUninterruptibly( );
|
||||
this.terminationLock.unlock( );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void run( )
|
||||
{
|
||||
this.initialiseBeans( );
|
||||
this.waitForTermination( );
|
||||
ToolBase.destroyContext( this.applicationContext );
|
||||
}
|
||||
|
||||
|
||||
public void terminate( )
|
||||
{
|
||||
this.terminationLock.lock( );
|
||||
this.termination.signal( );
|
||||
this.terminationLock.unlock( );
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package com.deepclone.lw.srv;
|
||||
|
||||
|
||||
public interface ServerTerminator
|
||||
{
|
||||
|
||||
public void terminate( );
|
||||
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package com.deepclone.lw.srv;
|
||||
|
||||
|
||||
public class ServerTerminatorBean
|
||||
implements ServerTerminator
|
||||
{
|
||||
|
||||
private Server server = null;
|
||||
|
||||
|
||||
public void setServer( Server server )
|
||||
{
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void terminate( )
|
||||
{
|
||||
if ( this.server != null ) {
|
||||
this.server.terminate( );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
|
||||
|
||||
<context:annotation-config />
|
||||
|
||||
</beans>
|
38
legacyworlds-server-main/src/main/resources/log4j.properties
Normal file
38
legacyworlds-server-main/src/main/resources/log4j.properties
Normal file
|
@ -0,0 +1,38 @@
|
|||
log4j.appender.fullDebug=org.apache.log4j.RollingFileAppender
|
||||
log4j.appender.fullDebug.File=./full-debug.log
|
||||
log4j.appender.fullDebug.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.fullDebug.layout.ConversionPattern=%d{yyyy-MM-dd@HH:mm:ss} %5p (%40c{1}:%-5L) - %m%n
|
||||
log4j.appender.fullDebug.MaxFileSize=100MB
|
||||
log4j.appender.fullDebug.MaxBackupIndex=1
|
||||
|
||||
log4j.appender.server=com.deepclone.lw.srv.LogAppender
|
||||
log4j.appender.server.File=./server.log
|
||||
log4j.appender.server.Threshold=DEBUG
|
||||
log4j.appender.server.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.server.layout.ConversionPattern=%d{yyyy-MM-dd@HH:mm:ss} %5p - %m%n
|
||||
log4j.appender.server.DatePattern='.'yyyy-MM-dd
|
||||
log4j.appender.server.MaxNumberOfDays=30
|
||||
log4j.appender.server.CompressBackups = true
|
||||
|
||||
log4j.appender.consoleError=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.consoleError.Target=System.out
|
||||
log4j.appender.consoleError.Threshold=WARN
|
||||
log4j.appender.consoleError.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.consoleError.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
|
||||
|
||||
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.stdout.Target=System.out
|
||||
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
|
||||
|
||||
|
||||
#log4j.logger.org.springframework=DEBUG, consoleError, fullDebug
|
||||
#log4j.logger.org.hibernate=DEBUG, consoleError, fullDebug
|
||||
#log4j.logger.com.deepclone.lw=DEBUG, stdout, fullDebug
|
||||
#log4j.logger.com.deepclone.lw.interfaces.eventlog=TRACE, fullDebug, server
|
||||
|
||||
|
||||
log4j.logger.org.springframework=WARN, server
|
||||
log4j.logger.org.springframework=INFO, fullDebug
|
||||
log4j.logger.com.deepclone.lw=DEBUG, fullDebug
|
||||
log4j.logger.com.deepclone.lw.interfaces.eventlog=DEBUG, server
|
27
legacyworlds-server-main/src/main/resources/lw-server.xml
Normal file
27
legacyworlds-server-main/src/main/resources/lw-server.xml
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
|
||||
xsi:schemaLocation="
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
|
||||
|
||||
<context:annotation-config />
|
||||
|
||||
<!-- Server terminator bean -->
|
||||
<bean id="terminator" class="com.deepclone.lw.srv.ServerTerminatorBean" />
|
||||
|
||||
<!-- Load transaction manager -->
|
||||
<import resource="configuration/transaction-bean.xml" />
|
||||
|
||||
<!-- Load all server beans -->
|
||||
<import resource="configuration/accounts-beans.xml" />
|
||||
<import resource="configuration/bt-beans.xml" />
|
||||
<import resource="configuration/eventlog-beans.xml" />
|
||||
<import resource="configuration/i18n-beans.xml" />
|
||||
<import resource="configuration/mailer-beans.xml" />
|
||||
<import resource="configuration/naming-beans.xml" />
|
||||
<import resource="configuration/simple-beans.xml" />
|
||||
<import resource="configuration/system-beans.xml" />
|
||||
<import resource="configuration/user-beans.xml" />
|
||||
|
||||
</beans>
|
0
legacyworlds-server-main/src/test/java/.empty
Normal file
0
legacyworlds-server-main/src/test/java/.empty
Normal file
0
legacyworlds-server-main/src/test/resources/.empty
Normal file
0
legacyworlds-server-main/src/test/resources/.empty
Normal file
Reference in a new issue