Importing SVN archives - B6M1

This commit is contained in:
Emmanuel BENOîT 2018-10-23 09:38:02 +02:00
commit fc4c6bd340
1695 changed files with 98617 additions and 0 deletions

17
.project Normal file
View file

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>legacyworlds</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.maven.ide.eclipse.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.maven.ide.eclipse.maven2Nature</nature>
</natures>
</projectDescription>

51
build-tools/BUILD.sh Executable file
View file

@ -0,0 +1,51 @@
#!/bin/sh
cd `dirname $0`/..
SRCDIR=`pwd`
if [ "x$1" = "x" ]; then
OUTDIR="$SRCDIR";
else
OUTDIR="$1";
fi
echo "Building Legacy Worlds..."
mvn clean || { echo "Maven clean-up failed"; exit 1; };
mvn package || { echo "Maven build failed"; exit 1; };
echo "Copying files..."
TEMPDIR=`mktemp -d`
mkdir $TEMPDIR/legacyworlds
mkdir $TEMPDIR/legacyworlds/server
mkdir $TEMPDIR/legacyworlds/server/data
mkdir $TEMPDIR/legacyworlds/web
mkdir $TEMPDIR/legacyworlds/sql
# Database and initial data
cp -Rapv legacyworlds-server/legacyworlds-server-data/db-structure/database.sql $TEMPDIR/legacyworlds/sql
cp -Rapv legacyworlds-server/legacyworlds-server-data/db-structure/db-config.txt $TEMPDIR/legacyworlds/sql/db-config-example.txt
cp -Rapv legacyworlds-server/legacyworlds-server-data/db-structure/parts $TEMPDIR/legacyworlds/sql
cp -Rapv legacyworlds-server/legacyworlds-server-main/data/* $TEMPDIR/legacyworlds/server/data
# Server
cp -Rapv legacyworlds-server/legacyworlds-server-main/target/*.jar $TEMPDIR/legacyworlds/server
cp -Rapv legacyworlds-server/legacyworlds-server-main/target/lib $TEMPDIR/legacyworlds/server
cp -Rapv legacyworlds-server/legacyworlds-server-main/data-source.xml $TEMPDIR/legacyworlds/server/data-source-example.xml
# Tools
cp -Rapv build-tools/server-config-example.sh $TEMPDIR/legacyworlds
cp -Rapv build-tools/start-server.sh $TEMPDIR/legacyworlds
cp -Rapv build-tools/stop-server.sh $TEMPDIR/legacyworlds
cp -Rapv build-tools/execute-clit.sh $TEMPDIR/legacyworlds
cp -Rapv build-tools/deploy.sh $TEMPDIR/legacyworlds
# Web sites
cp -Rapv legacyworlds-web/legacyworlds-web-*/target/*.war $TEMPDIR/legacyworlds/web
echo "Preparing archive..."
cd $TEMPDIR
find $TEMPDIR/legacyworlds -type d -name .svn | xargs rm -rf
tar cvjf $OUTDIR/legacyworlds.tar.bz2 legacyworlds || { echo "Archive generation failed"; exit 1; };
echo "Removing temporary directory..."
cd $SRCDIR
rm -rf $TEMPDIR
echo "All done. Legacy Worlds archive: $OUTDIR/legacyworlds.tar.bz2"

34
build-tools/deploy.sh Executable file
View file

@ -0,0 +1,34 @@
#!/bin/sh
COREDIR="$1"
if [ "x$COREDIR" = "x" ] || ! [ -d "$COREDIR" ]; then
echo "Syntax: $0 main_dir tomcat_dir web_dir"
exit 1;
fi
TOMCATDIR="$2"
if [ "x$TOMCATDIR" = "x" ] || ! [ -d "$TOMCATDIR" ]; then
echo "Syntax: $0 main_dir tomcat_dir web_dir"
exit 1;
fi
WEBDIR="$3"
if [ "x$WEBDIR" = "x" ] || ! [ -d "$WEBDIR" ]; then
echo "Syntax: $0 main_dir tomcat_dir web_dir"
exit 1;
fi
cd `dirname $0`
SRCDIR=`pwd`
cp -Rap server web *-*.sh $COREDIR
cd "$TOMCATDIR"
if [ -L "lwmain.war" ]; then
rm -f lwmain.war lwadmin.war
fi
ln -s "$COREDIR/web/legacyworlds-web-main-"*.war lwmain.war
ln -s "$COREDIR/web/legacyworlds-web-admin-"*.war lwadmin.war
cd $WEBDIR
unzip -o $COREDIR/web/legacyworlds-web-main-*.war "css/*" "js/*" "pjirc/*" "img/*"

5
build-tools/execute-clit.sh Executable file
View file

@ -0,0 +1,5 @@
#!/bin/sh
BASE="`dirname $0`"
cd "$BASE/server"
source server-config.sh
java $LOG -jar legacyworlds-server-main-*.jar --run-tool $1 "$2"

View file

@ -0,0 +1 @@
LOG="-Dlog4j.configuration=log4j.properties"

9
build-tools/start-server.sh Executable file
View file

@ -0,0 +1,9 @@
#!/bin/sh
BASE="`dirname $0`"
cd "$BASE/server"
source server-config.sh
if [ "x$1" = "x--debug" ]; then
java $LOG -jar legacyworlds-server-main-*.jar
else
( java $LOG -jar legacyworlds-server-main-*.jar </dev/null >/dev/null 2>&1 & ) </dev/null >/dev/null 2>&1 &
fi

2
build-tools/stop-server.sh Executable file
View file

@ -0,0 +1,2 @@
#!/bin/sh
"`dirname $0`"/execute-clit.sh Stop

269
eclipse-code-format.xml Normal file
View file

@ -0,0 +1,269 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<profiles version="11">
<profile kind="CodeFormatterProfile" name="Legacy Worlds" version="11">
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="48"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
<setting id="org.eclipse.jdt.core.compiler.source" value="1.5"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="120"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="17"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
<setting id="org.eclipse.jdt.core.compiler.problem.assertIdentifier" value="error"/>
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="tab"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="next_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.compiler.problem.enumIdentifier" value="error"/>
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="next_line"/>
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="17"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
<setting id="org.eclipse.jdt.core.compiler.compliance" value="1.5"/>
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="17"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="insert"/>
<setting id="org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode" value="enabled"/>
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="100"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="next_line"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_binary_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="17"/>
<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="17"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="1.5"/>
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="next_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="3"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
</profile>
</profiles>

View file

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>legacyworlds-server</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.maven.ide.eclipse.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.maven.ide.eclipse.maven2Nature</nature>
</natures>
</projectDescription>

View file

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>legacyworlds-server-beans</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.maven.ide.eclipse.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.maven.ide.eclipse.maven2Nature</nature>
</natures>
</projectDescription>

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java"/>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View file

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>legacyworlds-server-beans-accounts</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.maven.ide.eclipse.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.maven.ide.eclipse.maven2Nature</nature>
</natures>
</projectDescription>

View file

@ -0,0 +1,6 @@
#Fri Apr 09 10:19:20 CEST 2010
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=1.6

View file

@ -0,0 +1,15 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>legacyworlds-server-beans</artifactId>
<groupId>com.deepclone.lw</groupId>
<version>5.99.1</version>
</parent>
<groupId>com.deepclone.lw</groupId>
<artifactId>legacyworlds-server-beans-accounts</artifactId>
<name>Legacy Worlds account management</name>
<version>5.99.1</version>
<description>This package contains the beans responsible for managing accounts, including registration, inactivity checks, bans and authentication.</description>
</project>

View file

@ -0,0 +1,75 @@
package com.deepclone.lw.beans.acm;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.support.TransactionTemplate;
import com.deepclone.lw.interfaces.acm.UsersDAO;
import com.deepclone.lw.interfaces.mailer.Mailer;
import com.deepclone.lw.interfaces.sys.Ticker;
import com.deepclone.lw.interfaces.sys.Ticker.Frequency;
public class AccountCleanupBean
implements InitializingBean , DisposableBean
{
private TransactionTemplate tTemplate;
private Ticker ticker;
private UsersDAO usersDao;
private Mailer mailer;
private AccountCleanupTask cleanupTask;
@Autowired( required = true )
public void setTransactionManager( PlatformTransactionManager tManager )
{
this.tTemplate = new TransactionTemplate( tManager );
}
@Autowired( required = true )
public void setTicker( Ticker ticker )
{
this.ticker = ticker;
}
@Autowired( required = true )
public void setUsersDAO( UsersDAO usersDao )
{
this.usersDao = usersDao;
}
@Autowired( required = true )
public void setMailer( Mailer mailer )
{
this.mailer = mailer;
}
@Override
public void afterPropertiesSet( )
throws Exception
{
this.cleanupTask = new AccountCleanupTask( this.tTemplate , this.usersDao , this.mailer );
this.ticker.registerTask( Frequency.MEDIUM , "Accounts clean-up task" , this.cleanupTask );
}
@Override
public void destroy( )
{
this.cleanupTask = null;
}
}

View file

@ -0,0 +1,96 @@
package com.deepclone.lw.beans.acm;
import java.util.List;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import com.deepclone.lw.interfaces.acm.UsersDAO;
import com.deepclone.lw.interfaces.mailer.Mailer;
import com.deepclone.lw.sqld.accounts.QuittingAccount;
class AccountCleanupTask
implements Runnable
{
private TransactionTemplate tTemplate;
private UsersDAO usersDao;
private Mailer mailer;
public AccountCleanupTask( TransactionTemplate tTemplate , UsersDAO usersDao , Mailer mailer )
{
this.tTemplate = tTemplate;
this.usersDao = usersDao;
this.mailer = mailer;
}
@Override
public void run( )
{
this.sendInactivityWarnings( );
this.disableInactiveAccounts( );
this.dropOldAccounts( );
}
private void sendInactivityWarnings( )
{
List< QuittingAccount > toWarn;
toWarn = this.tTemplate.execute( new TransactionCallback< List< QuittingAccount >>( ) {
@Override
public List< QuittingAccount > doInTransaction( TransactionStatus status )
{
return usersDao.getInactivesToWarn( );
}
} );
for ( QuittingAccount account : toWarn ) {
try {
this.mailer.createMail( account.getLanguage( ) , "inactivityWarningMail" , account.getAddress( ) )
.queue( );
} catch ( Exception e ) {
continue;
}
}
}
private void disableInactiveAccounts( )
{
List< QuittingAccount > toDisable;
toDisable = this.tTemplate.execute( new TransactionCallback< List< QuittingAccount >>( ) {
@Override
public List< QuittingAccount > doInTransaction( TransactionStatus status )
{
return usersDao.getInactivesToDisable( );
}
} );
for ( QuittingAccount account : toDisable ) {
try {
this.mailer.createMail( account.getLanguage( ) , "inactivityQuitMail" , account.getAddress( ) ).queue( );
} catch ( Exception e ) {
continue;
}
}
}
private void dropOldAccounts( )
{
this.tTemplate.execute( new TransactionCallbackWithoutResult( ) {
@Override
protected void doInTransactionWithoutResult( TransactionStatus status )
{
usersDao.deleteOldAccounts( );
}
} );
}
}

View file

@ -0,0 +1,757 @@
package com.deepclone.lw.beans.acm;
import java.net.InetAddress;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import com.deepclone.lw.cmd.admin.adata.Administrator;
import com.deepclone.lw.cmd.admin.bans.ValidatedBanRequest;
import com.deepclone.lw.cmd.admin.logs.LogLevel;
import com.deepclone.lw.cmd.admin.users.AccountListEntry;
import com.deepclone.lw.cmd.admin.users.AccountSessionEntry;
import com.deepclone.lw.cmd.admin.users.AccountStatus;
import com.deepclone.lw.cmd.admin.users.AccountViewEntry;
import com.deepclone.lw.cmd.admin.users.SessionTerminationType;
import com.deepclone.lw.cmd.admin.users.UserSession;
import com.deepclone.lw.cmd.ext.ListLanguagesResponse;
import com.deepclone.lw.cmd.player.account.BanDetailsResponse;
import com.deepclone.lw.cmd.player.gdata.account.AccountData;
import com.deepclone.lw.cmd.player.gdata.account.PrefCategory;
import com.deepclone.lw.cmd.player.gdata.account.PrefChoice;
import com.deepclone.lw.cmd.player.gdata.account.PrefType;
import com.deepclone.lw.cmd.player.gdata.account.PrefValue;
import com.deepclone.lw.interfaces.acm.*;
import com.deepclone.lw.interfaces.admin.BansDAO;
import com.deepclone.lw.interfaces.eventlog.*;
import com.deepclone.lw.interfaces.i18n.*;
import com.deepclone.lw.interfaces.mailer.*;
import com.deepclone.lw.interfaces.naming.NamingDAO;
import com.deepclone.lw.interfaces.prefs.Preference;
import com.deepclone.lw.interfaces.prefs.PreferenceGroup;
import com.deepclone.lw.interfaces.prefs.PreferenceType;
import com.deepclone.lw.interfaces.prefs.PreferencesDAO;
import com.deepclone.lw.sqld.accounts.*;
import com.deepclone.lw.utils.*;
public class AccountManagementBean
implements AccountManagement
{
private TransactionTemplate tTemplate;
private Mailer mailer;
private Logger logger;
private UsersDAO usersDao;
private UserSessionDAO sessionDao;
private NamingDAO namingDao;
private Translator translator;
private PreferencesDAO prefsDao;
private BansDAO bansDao;
@Autowired( required = true )
public void setTransactionTemplate( PlatformTransactionManager transactionManager )
{
this.tTemplate = new TransactionTemplate( transactionManager );
}
@Autowired( required = true )
public void setMailer( Mailer mailer )
{
this.mailer = mailer;
}
@Autowired( required = true )
public void setLogger( Logger logger )
{
this.logger = logger;
}
@Autowired( required = true )
public void setUsersDao( UsersDAO usersDao )
{
this.usersDao = usersDao;
}
@Autowired( required = true )
public void setSessionDao( UserSessionDAO sessionDao )
{
this.sessionDao = sessionDao;
}
@Autowired( required = true )
public void setNamingDao( NamingDAO namingDao )
{
this.namingDao = namingDao;
}
@Autowired( required = true )
public void setTranslator( Translator translator )
{
this.translator = translator;
}
@Autowired( required = true )
public void setPrefsDao( PreferencesDAO prefsDao )
{
this.prefsDao = prefsDao;
}
@Autowired( required = true )
public void setBansDao( BansDAO bansDao )
{
this.bansDao = bansDao;
}
@Override
public void createAccount( final EmailAddress address , final Password password , final String language )
throws AccountMailException , MailerException , TranslationException
{
SystemLogger sLog = this.logger.getSystemLogger( "AccountManagement" );
sLog.log( LogLevel.INFO , "Attempting to create account '" + address.getAddress( ) + "'" ).flush( );
// Create credentials
AccountOperationResult result;
result = this.tTemplate.execute( new TransactionCallback< AccountOperationResult >( ) {
@Override
public AccountOperationResult doInTransaction( TransactionStatus status )
{
AccountOperationResult r = usersDao.createAccount( address , password , language );
if ( r.getErrorCode( ) != 0 ) {
status.setRollbackOnly( );
}
return r;
}
} );
// Check creation status
switch ( result.getErrorCode( ) ) {
case 0:
break;
case -1:
sLog.log( LogLevel.INFO , "Could not create account '" + address.getAddress( ) + "' - it exists" )
.flush( );
throw new AccountMailException( );
case -2:
sLog
.log( LogLevel.INFO ,
"Could not create account '" + address.getAddress( ) + "' - unknown language" ).flush( );
throw new UnknownLanguageException( language );
default:
sLog.log(
LogLevel.ERROR ,
"Could not create account '" + address.getAddress( ) + "' - unknown error code "
+ result.getErrorCode( ) ).flush( );
throw new RuntimeException( );
}
// Send email
Account account = result.getAccount( );
MailData data = this.mailer.createMail( language , "registrationMail" , address.getAddress( ) );
data.setData( "address" , address.getAddress( ) );
data.setData( "validationKey" , account.getValidationToken( ) );
try {
data.sendNow( );
} catch ( MailerException e ) {
this.cancelValidation( account );
sLog.log( LogLevel.INFO , "Could not create account '" + address.getAddress( ) + "'" , e ).flush( );
if ( e instanceof NotSentException ) {
throw e;
}
throw new RuntimeException( e );
}
}
private void cancelValidation( final Account account )
{
this.tTemplate.execute( new TransactionCallbackWithoutResult( ) {
@Override
protected void doInTransactionWithoutResult( TransactionStatus status )
{
usersDao.cancelAccountValidation( account );
}
} );
}
@Override
public void reactivateAccount( final EmailAddress address )
throws AccountMailException , MailerException
{
SystemLogger sLog = this.logger.getSystemLogger( "AccountManagement" );
sLog.log( LogLevel.INFO , "trying to re-activate account " + address.getAddress( ) ).flush( );
// Check status
Account account = this.tTemplate.execute( new TransactionCallback< Account >( ) {
@Override
public Account doInTransaction( TransactionStatus status )
{
Account r = usersDao.reactivateAccount( address );
if ( r == null ) {
status.setRollbackOnly( );
}
return r;
}
} );
if ( account == null ) {
throw new AccountMailException( );
}
// Send email
MailData data;
try {
data = this.mailer.createMail( account.getLanguage( ) , "reactivationMail" , address.getAddress( ) );
} catch ( TranslationException e ) {
sLog.log( LogLevel.ERROR , "'" + address.getAddress( ) + "' - error while preparing reactivation mail" , e )
.flush( );
this.cancelValidation( account );
throw new RuntimeException( e );
}
data.setData( "address" , account.getAddress( ) );
data.setData( "token" , account.getValidationToken( ) );
try {
data.sendNow( );
} catch ( MailerException e ) {
this.cancelValidation( account );
if ( e instanceof NotSentException ) {
throw e;
}
throw new RuntimeException( e );
}
}
@Override
public ValidationResult validateAccount( final EmailAddress address , final String token , final String empire ,
final String planet )
{
SystemLogger sLog = this.logger.getSystemLogger( "AccountManagement" );
sLog.log( LogLevel.INFO , "trying to validate account '" + address.getAddress( ) + "'" ).flush( );
return this.tTemplate.execute( new TransactionCallback< ValidationResult >( ) {
@Override
public ValidationResult doInTransaction( TransactionStatus status )
{
ValidationResult r = usersDao.validateAccount( address , token , empire , planet );
if ( r.isError( ) ) {
status.setRollbackOnly( );
}
return r;
}
} );
}
@Override
public void requestPasswordRecovery( final EmailAddress address )
throws AccountMailException , MailerException , PasswordRecoveryException
{
SystemLogger sLog = this.logger.getSystemLogger( "AccountManagement" );
sLog.log( LogLevel.INFO , "'" + address.getAddress( ) + "' requesting password recovery" ).flush( );
AccountOperationResult result = this.tTemplate.execute( new TransactionCallback< AccountOperationResult >( ) {
@Override
public AccountOperationResult doInTransaction( TransactionStatus status )
{
AccountOperationResult r = usersDao.requestPasswordRecovery( address );
if ( r.getErrorCode( ) != 0 ) {
status.setRollbackOnly( );
}
return r;
}
} );
// Throw exceptions as needed
switch ( result.getErrorCode( ) ) {
case 0:
break;
case 1:
sLog.log( LogLevel.INFO , "'" + address.getAddress( ) + "' - duplicate password recovery request" )
.flush( );
throw new PasswordRecoveryException( false );
case 2:
sLog.log( LogLevel.INFO , "'" + address.getAddress( ) + "' - account does not exist" ).flush( );
throw new AccountMailException( );
default:
sLog.log( LogLevel.ERROR , "Unknown error code " + result.getErrorCode( ) ).flush( );
throw new RuntimeException( );
}
// Send email
MailData data;
Account account = result.getAccount( );
try {
data = this.mailer.createMail( account.getLanguage( ) , "passwordRecoveryMail" , address.getAddress( ) );
} catch ( TranslationException e ) {
sLog.log( LogLevel.ERROR , "'" + address.getAddress( ) + "' - error while preparing recovery mail" , e )
.flush( );
this.cancelPasswordRecovery( account );
throw new RuntimeException( e );
}
data.setData( "address" , address.getAddress( ) );
data.setData( "token" , account.getPwdRecoveryToken( ) );
try {
data.sendNow( );
} catch ( MailerException e ) {
this.cancelPasswordRecovery( account );
if ( e instanceof NotSentException ) {
throw e;
}
throw new RuntimeException( e );
}
}
private void cancelPasswordRecovery( final Account account )
{
this.tTemplate.execute( new TransactionCallbackWithoutResult( ) {
@Override
protected void doInTransactionWithoutResult( TransactionStatus status )
{
usersDao.cancelPasswordRecovery( account );
}
} );
}
@Override
public void recoverPassword( final EmailAddress address , final String token , final Password password )
throws AccountMailException , PasswordRecoveryException , PasswordProhibitedException
{
SystemLogger sLog = this.logger.getSystemLogger( "AccountManagement" );
sLog.log( LogLevel.INFO , "'" + address.getAddress( ) + "' confirming password recovery" ).flush( );
AccountOperationResult result = this.tTemplate.execute( new TransactionCallback< AccountOperationResult >( ) {
@Override
public AccountOperationResult doInTransaction( TransactionStatus status )
{
AccountOperationResult r = usersDao.confirmPasswordRecovery( address , token , password );
if ( r.getErrorCode( ) != 0 ) {
status.setRollbackOnly( );
}
return r;
}
} );
// Handle errors
switch ( result.getErrorCode( ) ) {
case 0:
break;
case 1:
throw new AccountMailException( );
case 2:
throw new PasswordProhibitedException( );
default:
sLog.log( LogLevel.ERROR , "Unknown error code " + result.getErrorCode( ) ).flush( );
throw new RuntimeException( );
}
}
@Override
@Transactional
public AccountSession login( final EmailAddress address , String challenge , String sha1Hash , String md5Hash ,
InetAddress ipAddress , String clientType , String sessionName )
{
Account account = this.usersDao.getAccount( address );
// Check account
if ( account == null ) {
SystemLogger sLog = this.logger.getSystemLogger( "AccountManagement" );
sLog.log( LogLevel.INFO , "login attempt for unknown address '" + address.getAddress( ) + "'" ).flush( );
return null;
}
// Check challenge response
String eSha1 = DigestHelper.digest( "sha-1" , challenge + " " + account.getPassSha1( ) );
String eMd5 = DigestHelper.digest( "md5" , challenge + " " + account.getPassMd5( ) );
if ( ! ( eSha1.equals( sha1Hash ) && eMd5.equals( md5Hash ) ) ) {
return null;
}
// Create session
long sId = this.sessionDao.startSession( account.getId( ) , sessionName , clientType , ipAddress.toString( ) );
return new AccountSession( account , sId );
}
@Override
@Transactional
public void logout( long session , SessionTerminationType reason )
{
this.sessionDao.endSession( session , reason );
}
@Override
@Transactional
public Account restoreSession( long session )
{
UserSession sData = this.sessionDao.getSession( session );
if ( sData == null || sData.getEndType( ) != null ) {
return null;
}
return this.usersDao.getAccount( sData.getCredentialsId( ) );
}
@Override
@Transactional
public Account getAccount( final EmailAddress address )
{
return this.usersDao.getAccount( address );
}
@Override
@Transactional
public List< String > getEmpireNames( final EmailAddress address )
{
Account accnt = this.usersDao.getAccount( address );
if ( accnt == null ) {
return null;
}
return this.namingDao.getEmpireNames( accnt.getId( ) );
}
@Override
@Transactional
public AccountData getAccountPage( EmailAddress address )
{
Account account = this.getAccount( address );
return this.accountToPage( account );
}
private AccountData accountToPage( Account account )
{
AccountData data = new AccountData( );
data.setAddress( account.getAddress( ) );
data.setGameCredits( account.getGameCredits( ) );
data.setLanguage( account.getLanguage( ) );
data.setQuitGame( account.getInactivityStart( ) );
data.setVacCredits( account.getVacationCredits( ) );
data.setVacTime( account.getVacationTime( ) );
data.setVacStart( account.getVacationStart( ) );
data.setMailChange( this.usersDao.getMailChange( account.getId( ) ) );
// Get supported languages
Map< String , String > languages = new HashMap< String , String >( );
try {
for ( String lId : this.translator.getSupportedLanguages( ) ) {
languages.put( lId , this.translator.getLanguageName( lId ) );
}
} catch ( UnknownLanguageException e ) {
throw new RuntimeException( e );
}
data.setSupportedLanguages( new ListLanguagesResponse( languages ) );
// Extract account preferences
for ( PreferenceGroup group : this.prefsDao.getPreferences( account ).getGroups( ) ) {
PrefCategory pCat = new PrefCategory( );
pCat.setName( group.getDisplay( ) );
for ( Preference pref : group.getPreferences( ) ) {
PrefValue pValue = new PrefValue( );
pValue.setId( pref.getName( ) );
pValue.setName( pref.getDisplayName( ) );
pValue.setDescription( pref.getDescription( ) );
PreferenceType< ? > dType = pref.getType( );
if ( dType.getType( ) == String.class ) {
pValue.setType( PrefType.STRING );
} else if ( dType.getType( ) == Integer.class ) {
pValue.setType( PrefType.INTEGER );
} else if ( dType.getType( ) == Boolean.class ) {
pValue.setType( PrefType.BOOLEAN );
} else {
Map< String , String > choices = dType.getChoices( );
List< PrefChoice > cList = new LinkedList< PrefChoice >( );
for ( Map.Entry< String , String > entry : choices.entrySet( ) ) {
String name;
try {
name = this.translator.translate( data.getLanguage( ) , entry.getValue( ) );
} catch ( TranslationException e ) {
throw new RuntimeException( e );
}
cList.add( new PrefChoice( entry.getKey( ) , name ) );
}
pValue.setType( PrefType.CHOICE );
pValue.setChoices( cList );
}
pValue.setValue( pref.getDBValue( ) );
pCat.addValue( pValue );
}
data.addPreferenceCategory( pCat );
}
return data;
}
@Override
@Transactional
public void setLanguage( EmailAddress address , String language )
{
this.usersDao.setLanguage( address , language );
}
@Override
@Transactional
public boolean setPassword( final EmailAddress address , String challenge , String sha1Hash , String md5Hash ,
Password newPassword )
throws PasswordProhibitedException
{
Account account = this.usersDao.getAccount( address );
// Check challenge response
String eSha1 = DigestHelper.digest( "sha-1" , challenge + " " + account.getPassSha1( ) );
String eMd5 = DigestHelper.digest( "md5" , challenge + " " + account.getPassMd5( ) );
if ( ! ( eSha1.equals( sha1Hash ) && eMd5.equals( md5Hash ) ) ) {
return false;
}
if ( !this.usersDao.setPassword( account , newPassword ) ) {
throw new PasswordProhibitedException( );
}
return true;
}
@Override
@Transactional( rollbackFor = {
RuntimeException.class , AccountMailException.class , MailerException.class
} )
public boolean setAddress( EmailAddress address , String challenge , String sha1Hash , String md5Hash ,
EmailAddress nAddress )
throws AccountMailException , MailerException
{
Account account = this.usersDao.getAccount( address );
// Check challenge response
String eSha1 = DigestHelper.digest( "sha-1" , challenge + " " + account.getPassSha1( ) );
String eMd5 = DigestHelper.digest( "md5" , challenge + " " + account.getPassMd5( ) );
if ( ! ( eSha1.equals( sha1Hash ) && eMd5.equals( md5Hash ) ) ) {
return false;
}
int errCode = this.usersDao.setAddress( account , nAddress );
switch ( errCode ) {
case -1:
return true;
case -2:
throw new AccountMailException( );
}
// Send email
SystemLogger sLog = this.logger.getSystemLogger( "AccountManagement" );
MailData data;
account = this.usersDao.getAccount( address );
try {
data = this.mailer.createMail( account.getLanguage( ) , "addressChangeMail" , nAddress.getAddress( ) );
} catch ( TranslationException e ) {
sLog.log( LogLevel.ERROR , "'" + address.getAddress( ) + "' - error while preparing recovery mail" , e )
.flush( );
this.cancelPasswordRecovery( account );
throw new RuntimeException( e );
}
data.setData( "address" , nAddress.getAddress( ) );
data.setData( "token" , account.getAddressChangeToken( ) );
try {
data.sendNow( );
} catch ( MailerException e ) {
if ( e instanceof NotSentException ) {
throw e;
}
throw new RuntimeException( e );
}
return true;
}
@Override
@Transactional
public void cancelAddressChange( EmailAddress cAddress )
{
this.usersDao.cancelAddressChange( this.usersDao.getAccount( cAddress ) );
}
@Override
@Transactional
public AccountData confirmAddressChange( EmailAddress cAddress , String code )
{
Account account = this.usersDao.getAccount( cAddress );
if ( account.getAddressChangeToken( ) != null ) {
int newId = this.usersDao.confirmAddressChange( account , code );
account = this.usersDao.getAccount( newId );
}
return this.accountToPage( account );
}
@Override
@Transactional
public void resetPreferences( EmailAddress address )
{
Account account = this.usersDao.getAccount( address );
this.prefsDao.resetPreferences( account );
}
@Override
@Transactional
public void setPreferences( EmailAddress address , Map< String , String > values )
{
Account account = this.usersDao.getAccount( address );
this.prefsDao.setPreferences( account , values );
}
@Override
@Transactional
public void setQuit( EmailAddress address , String reason )
{
Account account = this.usersDao.getAccount( address );
if ( account.getStatus( ) == AccountStatus.ACTIVE ) {
this.usersDao.setQuit( account , reason );
}
}
@Override
@Transactional
public void cancelQuit( EmailAddress address )
{
Account account = this.usersDao.getAccount( address );
if ( account.getStatus( ) == AccountStatus.QUITTING ) {
this.usersDao.cancelQuit( account );
}
}
@Override
@Transactional
public void toggleVacation( EmailAddress address )
{
Account account = this.usersDao.getAccount( address );
AccountStatus status = account.getStatus( );
if ( status == AccountStatus.ACTIVE ) {
this.usersDao.enterVacation( account );
} else if ( status == AccountStatus.START_VACATION || status == AccountStatus.VACATION ) {
this.usersDao.leaveVacation( account );
}
}
@Override
@Transactional
public List< AccountListEntry > listAccounts( AccountStatus status , boolean online )
{
if ( online ) {
return this.usersDao.listOnlineAccounts( status );
}
return this.usersDao.listAccounts( status );
}
@Override
@Transactional
public AccountViewEntry getAccountView( int id )
{
AccountViewEntry basics = this.usersDao.viewAccount( id );
if ( basics == null ) {
return null;
}
basics.setOnline( this.sessionDao.isOnline( id ) );
basics.setEmpireNames( this.namingDao.getEmpireNames( id ) );
return basics;
}
@Override
@Transactional
public AccountSessionEntry viewSessions( int id )
{
AccountViewEntry basics = this.usersDao.viewAccount( id );
if ( basics == null ) {
return null;
}
AccountSessionEntry entry = new AccountSessionEntry( basics );
entry.setSessions( this.sessionDao.getSessions( id ) );
return entry;
}
@Override
@Transactional
public void giveCredits( Administrator admin , int id , int credits )
{
this.usersDao.giveCredits( admin.getId( ) , id , credits );
}
@Override
@Transactional
public BanDetailsResponse getBanDetails( EmailAddress address )
{
ValidatedBanRequest ban = this.bansDao.getActiveBan( address );
if ( ban == null ) {
throw new RuntimeException( "account not banned" );
}
return new BanDetailsResponse( ban.getUpdate( ) , ban.getReason( ) , ban.isRedeemable( ) );
}
}

View file

@ -0,0 +1,75 @@
package com.deepclone.lw.beans.acm;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.support.TransactionTemplate;
import com.deepclone.lw.interfaces.acm.UsersDAO;
import com.deepclone.lw.interfaces.mailer.Mailer;
import com.deepclone.lw.interfaces.sys.Ticker;
import com.deepclone.lw.interfaces.sys.Ticker.Frequency;
public class QuitProcessorBean
implements InitializingBean , DisposableBean
{
private TransactionTemplate tTemplate;
private Ticker ticker;
private UsersDAO usersDao;
private Mailer mailer;
private QuitProcessorTask quitProcessor;
@Autowired( required = true )
public void setTransactionManager( PlatformTransactionManager tManager )
{
this.tTemplate = new TransactionTemplate( tManager );
}
@Autowired( required = true )
public void setTicker( Ticker ticker )
{
this.ticker = ticker;
}
@Autowired( required = true )
public void setUsersDAO( UsersDAO usersDao )
{
this.usersDao = usersDao;
}
@Autowired( required = true )
public void setMailer( Mailer mailer )
{
this.mailer = mailer;
}
@Override
public void afterPropertiesSet( )
throws Exception
{
this.quitProcessor = new QuitProcessorTask( this.tTemplate , this.usersDao , this.mailer );
this.ticker.registerTask( Frequency.MEDIUM , "Quitting accounts processor" , this.quitProcessor );
}
@Override
public void destroy( )
{
this.quitProcessor = null;
}
}

View file

@ -0,0 +1,53 @@
package com.deepclone.lw.beans.acm;
import java.util.List;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
import com.deepclone.lw.interfaces.acm.UsersDAO;
import com.deepclone.lw.interfaces.mailer.Mailer;
import com.deepclone.lw.sqld.accounts.QuittingAccount;
class QuitProcessorTask
implements Runnable
{
private TransactionTemplate tTemplate;
private UsersDAO usersDao;
private Mailer mailer;
public QuitProcessorTask( TransactionTemplate tTemplate , UsersDAO usersDao , Mailer mailer )
{
this.tTemplate = tTemplate;
this.usersDao = usersDao;
this.mailer = mailer;
}
@Override
public void run( )
{
List< QuittingAccount > quitters;
quitters = this.tTemplate.execute( new TransactionCallback< List< QuittingAccount >>( ) {
@Override
public List< QuittingAccount > doInTransaction( TransactionStatus status )
{
return usersDao.processQuits( );
}
} );
for ( QuittingAccount quitter : quitters ) {
try {
this.mailer.createMail( quitter.getLanguage( ) , "quitMail" , quitter.getAddress( ) ).queue( );
} catch ( Exception e ) {
continue;
}
}
}
}

View file

@ -0,0 +1,65 @@
package com.deepclone.lw.beans.acm;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.support.TransactionTemplate;
import com.deepclone.lw.interfaces.acm.UsersDAO;
import com.deepclone.lw.interfaces.sys.Ticker;
import com.deepclone.lw.interfaces.sys.Ticker.Frequency;
public class RequestsExpirationBean
implements InitializingBean , DisposableBean
{
private TransactionTemplate tTemplate;
private Ticker ticker;
private UsersDAO usersDao;
private RequestsExpirationTask expiration;
@Autowired( required = true )
public void setTransactionManager( PlatformTransactionManager tManager )
{
this.tTemplate = new TransactionTemplate( tManager );
}
@Autowired( required = true )
public void setTicker( Ticker ticker )
{
this.ticker = ticker;
}
@Autowired( required = true )
public void setUsersDAO( UsersDAO usersDao )
{
this.usersDao = usersDao;
}
@Override
public void afterPropertiesSet( )
throws Exception
{
this.expiration = new RequestsExpirationTask( this.tTemplate , this.usersDao );
this.ticker.registerTask( Frequency.MEDIUM , "Account requests expiration" , this.expiration );
}
@Override
public void destroy( )
{
this.expiration = null;
}
}

View file

@ -0,0 +1,38 @@
package com.deepclone.lw.beans.acm;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import com.deepclone.lw.interfaces.acm.UsersDAO;
class RequestsExpirationTask
implements Runnable
{
private TransactionTemplate tTemplate;
private UsersDAO usersDao;
public RequestsExpirationTask( TransactionTemplate tTemplate , UsersDAO usersDao )
{
this.tTemplate = tTemplate;
this.usersDao = usersDao;
}
@Override
public void run( )
{
this.tTemplate.execute( new TransactionCallbackWithoutResult( ) {
@Override
protected void doInTransactionWithoutResult( TransactionStatus status )
{
usersDao.expireRequests( );
}
} );
}
}

View file

@ -0,0 +1,137 @@
package com.deepclone.lw.beans.acm;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.List;
import javax.sql.DataSource;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
import com.deepclone.lw.cmd.admin.users.SessionTerminationType;
import com.deepclone.lw.cmd.admin.users.UserSession;
import com.deepclone.lw.interfaces.acm.UserSessionDAO;
import com.deepclone.lw.utils.StoredProc;
public class UserSessionDAOBean
implements UserSessionDAO , InitializingBean
{
private SimpleJdbcTemplate dTemplate;
private final RowMapper< UserSession > mSession;
private StoredProc fSessionStart;
private StoredProc fSessionEnd;
public UserSessionDAOBean( )
{
this.mSession = new RowMapper< UserSession >( ) {
@Override
public UserSession mapRow( ResultSet rs , int rowNum )
throws SQLException
{
UserSession session = new UserSession( );
session.setId( rs.getLong( "id" ) );
session.setCredentialsId( rs.getInt( "credentials_id" ) );
session.setSessionName( rs.getString( "session" ) );
session.setClientName( rs.getString( "client_name" ) );
session.setExclusive( rs.getBoolean( "exclusive" ) );
session.setFromAddress( rs.getString( "from_address" ) );
if ( session.getFromAddress( ).startsWith( "/" )) {
session.setFromAddress( session.getFromAddress( ).substring( 1 ) );
}
session.setStarted( rs.getTimestamp( "started" ) );
session.setEnded( rs.getTimestamp( "ended" ) );
if ( session.getEnded( ) != null ) {
session.setEndType( SessionTerminationType.valueOf( rs.getString( "end_type" ) ) );
}
return session;
}
};
}
@Autowired( required = true )
public void setDataSource( DataSource dataSource )
{
this.dTemplate = new SimpleJdbcTemplate( dataSource );
this.fSessionStart = new StoredProc( dataSource , "users" , "sessions_login" );
this.fSessionStart.addParameter( "credentials_id" , Types.INTEGER );
this.fSessionStart.addParameter( "session_name" , Types.VARCHAR );
this.fSessionStart.addParameter( "client_type" , Types.VARCHAR );
this.fSessionStart.addParameter( "ip_address" , Types.VARCHAR );
this.fSessionStart.addOutput( "s_id" , Types.BIGINT );
this.fSessionEnd = new StoredProc( dataSource , "users" , "sessions_terminate" );
this.fSessionEnd.addParameter( "session_id" , Types.BIGINT );
this.fSessionEnd.addParameter( "end_type" , "session_termination_type" );
}
@Override
public void afterPropertiesSet( )
{
this.dTemplate.getJdbcOperations( ).execute( "SELECT users.sessions_server_restart()" );
}
@Override
public long startSession( int id , String sName , String client , String address )
{
return (Long) this.fSessionStart.execute( id , sName , client , address ).get( "s_id" );
}
@Override
public void endSession( long session , SessionTerminationType termination )
{
this.fSessionEnd.execute( session , termination.toString( ) );
}
@Override
public UserSession getSession( long id )
{
String sql = "SELECT * FROM users.sessions WHERE id = ?";
try {
return this.dTemplate.queryForObject( sql , this.mSession , id );
} catch ( EmptyResultDataAccessException e ) {
return null;
}
}
@Override
public boolean isOnline( int id )
{
String sql = "SELECT credentials_id FROM users.sessions WHERE credentials_id = ? AND end_type IS NULL AND exclusive";
try {
this.dTemplate.queryForInt( sql , id );
return true;
} catch ( EmptyResultDataAccessException e ) {
return false;
}
}
@Override
public List< UserSession > getSessions( int id )
{
String sql = "SELECT * FROM users.sessions WHERE credentials_id = ?";
return this.dTemplate.query( sql , this.mSession , id );
}
}

View file

@ -0,0 +1,550 @@
package com.deepclone.lw.beans.acm;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
import com.deepclone.lw.cmd.admin.users.AccountBanEntry;
import com.deepclone.lw.cmd.admin.users.AccountListEntry;
import com.deepclone.lw.cmd.admin.users.AccountStatus;
import com.deepclone.lw.cmd.admin.users.AccountViewEntry;
import com.deepclone.lw.cmd.player.gdata.account.MailChangeData;
import com.deepclone.lw.interfaces.acm.UsersDAO;
import com.deepclone.lw.sqld.accounts.Account;
import com.deepclone.lw.sqld.accounts.AccountOperationResult;
import com.deepclone.lw.sqld.accounts.QuittingAccount;
import com.deepclone.lw.sqld.accounts.ValidationResult;
import com.deepclone.lw.utils.EmailAddress;
import com.deepclone.lw.utils.Password;
import com.deepclone.lw.utils.StoredProc;
public class UsersDAOBean
implements UsersDAO
{
private static abstract class AccountListMapper< T extends AccountListEntry >
implements RowMapper< T >
{
protected void getCommonColumns( AccountListEntry e , ResultSet rs )
throws SQLException
{
e.setId( rs.getInt( "id" ) );
e.setAddress( rs.getString( "address" ) );
e.setLanguage( rs.getString( "language" ) );
e.setStatus( AccountStatus.valueOf( rs.getString( "status" ) ) );
e.setCurrentEmpire( rs.getString( "current_empire" ) );
}
}
private final RowMapper< Account > accountMapper;
private final RowMapper< QuittingAccount > quitMapper;
private final RowMapper< MailChangeData > mailChangeMapper;
private final AccountListMapper< AccountListEntry > mAccountList;
private final AccountListMapper< AccountViewEntry > mAccountView;
private SimpleJdbcTemplate dTemplate;
private StoredProc fCreateAccount;
private StoredProc fMailFailure;
private StoredProc fValidate;
private StoredProc fReactivate;
private StoredProc fRequestPasswordRecovery;
private StoredProc fCancelPasswordRecovery;
private StoredProc fConfirmPasswordRecovery;
private StoredProc fSetLanguage;
private StoredProc fSetPassword;
private StoredProc fSetAddress;
private StoredProc fCancelAddressChange;
private StoredProc fConfirmAddressChange;
private StoredProc fSetQuit;
private StoredProc fCancelQuit;
private StoredProc fEnterVacation;
private StoredProc fLeaveVacation;
private StoredProc fGrantCredits;
public UsersDAOBean( )
{
this.accountMapper = new RowMapper< Account >( ) {
@Override
public Account mapRow( ResultSet rs , int rowNum )
throws SQLException
{
Account account = new Account( );
account.setId( rs.getInt( "id" ) );
account.setAddress( rs.getString( "address" ) );
account.setLanguage( rs.getString( "language" ) );
account.setPassMd5( rs.getString( "pass_md5" ) );
account.setPassSha1( rs.getString( "pass_sha1" ) );
account.setGameCredits( rs.getInt( "game_credits" ) );
account.setStatus( AccountStatus.valueOf( rs.getString( "status" ) ) );
account.setValidationToken( rs.getString( "validation_token" ) );
account.setPwdRecoveryToken( rs.getString( "pwd_recovery_token" ) );
account.setAddressChangeToken( rs.getString( "address_change_token" ) );
account.setNewAddress( rs.getString( "new_address" ) );
account.setVacationCredits( rs.getInt( "vacation_credits" ) );
account.setVacationTime( rs.getInt( "vacation_time" ) );
account.setVacationStart( rs.getTimestamp( "vacation_start" ) );
account.setInactivityStart( rs.getTimestamp( "inactivity_begin" ) );
account.setInactivityReason( rs.getString( "inactivity_reason" ) );
account.setBanRequestId( rs.getInt( "ban_request_id" ) );
return account;
}
};
this.mailChangeMapper = new RowMapper< MailChangeData >( ) {
@Override
public MailChangeData mapRow( ResultSet rs , int rowNum )
throws SQLException
{
if ( rs.getBoolean( "used" ) ) {
return new MailChangeData( rs.getTimestamp( "expires" ) );
}
return new MailChangeData( rs.getTimestamp( "expires" ) , rs.getString( "new_address" ) );
}
};
this.quitMapper = new RowMapper< QuittingAccount >( ) {
@Override
public QuittingAccount mapRow( ResultSet rs , int rowNum )
throws SQLException
{
QuittingAccount acc = new QuittingAccount( );
acc.setId( rs.getInt( "id" ) );
acc.setAddress( rs.getString( "address" ) );
acc.setLanguage( rs.getString( "language" ) );
return acc;
}
};
this.mAccountList = new AccountListMapper< AccountListEntry >( ) {
@Override
public AccountListEntry mapRow( ResultSet rs , int rowNum )
throws SQLException
{
AccountListEntry e = new AccountListEntry( );
this.getCommonColumns( e , rs );
return e;
}
};
this.mAccountView = new AccountListMapper< AccountViewEntry >( ) {
@Override
public AccountViewEntry mapRow( ResultSet rs , int rowNum )
throws SQLException
{
AccountViewEntry e = new AccountViewEntry( );
this.getCommonColumns( e , rs );
e.setGameCredits( rs.getInt( "game_credits" ) );
e.setVacationCredits( rs.getInt( "vacation_credits" ) );
if ( !e.getStatus( ).isActive( ) && e.getStatus( ) != AccountStatus.UNCONFIRMED ) {
e.setStatusStart( rs.getTimestamp( "inactivity_begin" ) );
} else {
e.setStatusStart( rs.getTimestamp( "vacation_start" ) );
}
e.setInactivityReason( rs.getString( "inactivity_reason" ) );
e.setEmpireId( (Integer) rs.getObject( "current_empire_id" ) );
if ( e.getStatus( ) == AccountStatus.BANNED ) {
AccountBanEntry ban = new AccountBanEntry( );
ban.setRequestedById( rs.getInt( "ban_req_id" ) );
ban.setRequestedByName( rs.getString( "ban_req_name" ) );
ban.setConfirmedById( rs.getInt( "ban_val_id" ) );
ban.setConfirmedByName( rs.getString( "ban_val_name" ) );
e.setBan( ban );
}
e.setWarnings( rs.getInt( "warnings_count" ) );
e.setLastWarning( rs.getTimestamp( "warnings_last" ) );
return e;
}
};
}
@Autowired( required = true )
public void setDataSource( DataSource dataSource )
{
this.dTemplate = new SimpleJdbcTemplate( dataSource );
this.fCreateAccount = new StoredProc( dataSource , "users" , "create_credentials" );
this.fCreateAccount.addParameter( "address" , Types.VARCHAR );
this.fCreateAccount.addParameter( "lang_id" , Types.VARCHAR );
this.fCreateAccount.addParameter( "pass_md5" , Types.VARCHAR );
this.fCreateAccount.addParameter( "pass_sha1" , Types.VARCHAR );
this.fCreateAccount.addOutput( "err_code" , Types.INTEGER );
this.fCreateAccount.addOutput( "a_id" , Types.INTEGER );
this.fMailFailure = new StoredProc( dataSource , "users" , "validation_mail_failure" );
this.fMailFailure.addParameter( "a_id" , Types.INTEGER );
this.fValidate = new StoredProc( dataSource , "users" , "validate" );
this.fValidate.addParameter( "addr" , Types.VARCHAR );
this.fValidate.addParameter( "vtoken" , Types.VARCHAR );
this.fValidate.addParameter( "empname" , Types.VARCHAR );
this.fValidate.addParameter( "plname" , Types.VARCHAR );
this.fValidate.addOutput( "account_error" , Types.INTEGER );
this.fValidate.addOutput( "empire_error" , Types.INTEGER );
this.fValidate.addOutput( "planet_error" , Types.INTEGER );
this.fReactivate = new StoredProc( dataSource , "users" , "reactivate" );
this.fReactivate.addParameter( "addr" , Types.VARCHAR );
this.fReactivate.addOutput( "success" , Types.BOOLEAN );
this.fReactivate.addOutput( "a_id" , Types.INTEGER );
this.fRequestPasswordRecovery = new StoredProc( dataSource , "users" , "request_password_recovery" );
this.fRequestPasswordRecovery.addParameter( "addr" , Types.VARCHAR );
this.fRequestPasswordRecovery.addOutput( "err_code" , Types.INTEGER );
this.fRequestPasswordRecovery.addOutput( "a_id" , Types.INTEGER );
this.fCancelPasswordRecovery = new StoredProc( dataSource , "users" , "cancel_password_recovery" );
this.fCancelPasswordRecovery.addParameter( "a_id" , Types.INTEGER );
this.fConfirmPasswordRecovery = new StoredProc( dataSource , "users" , "confirm_password_recovery" );
this.fConfirmPasswordRecovery.addParameter( "umail" , Types.VARCHAR );
this.fConfirmPasswordRecovery.addParameter( "tok" , Types.VARCHAR );
this.fConfirmPasswordRecovery.addParameter( "pmd5" , Types.VARCHAR );
this.fConfirmPasswordRecovery.addParameter( "psha1" , Types.VARCHAR );
this.fConfirmPasswordRecovery.addOutput( "err_code" , Types.INTEGER );
this.fConfirmPasswordRecovery.addOutput( "a_id" , Types.INTEGER );
this.fSetLanguage = new StoredProc( dataSource , "users" , "set_language" );
this.fSetLanguage.addParameter( "umail" , Types.VARCHAR );
this.fSetLanguage.addParameter( "lang_id" , Types.VARCHAR );
this.fSetPassword = new StoredProc( dataSource , "users" , "set_password" );
this.fSetPassword.addParameter( "u_id" , Types.INTEGER );
this.fSetPassword.addParameter( "pmd5" , Types.VARCHAR );
this.fSetPassword.addParameter( "psha1" , Types.VARCHAR );
this.fSetPassword.addOutput( "success" , Types.BOOLEAN );
this.fSetAddress = new StoredProc( dataSource , "users" , "request_address_change" );
this.fSetAddress.addParameter( "u_id" , Types.INTEGER );
this.fSetAddress.addParameter( "n_address" , Types.VARCHAR );
this.fSetAddress.addOutput( "err_code" , Types.INTEGER );
this.fCancelAddressChange = new StoredProc( dataSource , "users" , "cancel_address_change" );
this.fCancelAddressChange.addParameter( "u_id" , Types.INTEGER );
this.fConfirmAddressChange = new StoredProc( dataSource , "users" , "confirm_address_change" );
this.fConfirmAddressChange.addParameter( "u_id" , Types.INTEGER );
this.fConfirmAddressChange.addParameter( "token" , Types.VARCHAR );
this.fConfirmAddressChange.addOutput( "n_id" , Types.INTEGER );
this.fSetQuit = new StoredProc( dataSource , "users" , "set_account_quit" );
this.fSetQuit.addParameter( "accound_id" , Types.INTEGER );
this.fSetQuit.addParameter( "reason_text" , Types.VARCHAR );
this.fCancelQuit = new StoredProc( dataSource , "users" , "cancel_account_quit" );
this.fCancelQuit.addParameter( "account_id" , Types.INTEGER );
this.fEnterVacation = new StoredProc( dataSource , "users" , "set_vacation" );
this.fEnterVacation.addParameter( "account_id" , Types.INTEGER );
this.fLeaveVacation = new StoredProc( dataSource , "users" , "leave_vacation" );
this.fLeaveVacation.addParameter( "account_id" , Types.INTEGER );
this.fGrantCredits = new StoredProc( dataSource , "admin" , "grant_user_credits" );
this.fGrantCredits.addParameter( "admin_id" , Types.INTEGER );
this.fGrantCredits.addParameter( "account_id" , Types.INTEGER );
this.fGrantCredits.addParameter( "credits" , Types.INTEGER );
}
@Override
public Account getAccount( EmailAddress address )
{
String sql = "SELECT * FROM users.accounts_view WHERE address = ?";
try {
return this.dTemplate.queryForObject( sql , this.accountMapper , address.getAddress( ) );
} catch ( EmptyResultDataAccessException e ) {
return null;
}
}
@Override
public Account getAccount( int id )
{
String sql = "SELECT * FROM users.accounts_view WHERE id = ?";
try {
return this.dTemplate.queryForObject( sql , this.accountMapper , id );
} catch ( EmptyResultDataAccessException e ) {
return null;
}
}
private AccountOperationResult mapToResult( Map< String , Object > m )
{
int errCode = (Integer) m.get( "err_code" );
AccountOperationResult result = new AccountOperationResult( );
result.setErrorCode( errCode );
if ( errCode == 0 ) {
result.setAccount( this.getAccount( (Integer) m.get( "a_id" ) ) );
}
return result;
}
@Override
public AccountOperationResult createAccount( EmailAddress address , Password password , String language )
{
Map< String , Object > m = this.fCreateAccount.execute( address.getAddress( ) , language , password.getMd5( ) ,
password.getSha1( ) );
return this.mapToResult( m );
}
@Override
public void cancelAccountValidation( Account account )
{
this.fMailFailure.execute( account.getId( ) );
}
@Override
public ValidationResult validateAccount( EmailAddress address , String token , String eName , String pName )
{
Map< String , Object > m = this.fValidate.execute( address.getAddress( ) , token , eName , pName );
ValidationResult vr = new ValidationResult( );
vr.setAccountError( (Integer) m.get( "account_error" ) );
vr.setEmpireError( (Integer) m.get( "empire_error" ) );
vr.setPlanetError( (Integer) m.get( "planet_error" ) );
return vr;
}
@Override
public Account reactivateAccount( EmailAddress address )
{
Map< String , Object > m = this.fReactivate.execute( address.getAddress( ) );
boolean success = (Boolean) m.get( "success" );
if ( !success ) {
return null;
}
return this.getAccount( (Integer) m.get( "a_id" ) );
}
@Override
public AccountOperationResult requestPasswordRecovery( EmailAddress address )
{
Map< String , Object > m = this.fRequestPasswordRecovery.execute( address.getAddress( ) );
return this.mapToResult( m );
}
@Override
public void cancelPasswordRecovery( Account account )
{
this.fCancelPasswordRecovery.execute( account.getId( ) );
}
@Override
public AccountOperationResult confirmPasswordRecovery( EmailAddress address , String token , Password nPassword )
{
Map< String , Object > m = this.fConfirmPasswordRecovery.execute( address.getAddress( ) , token , nPassword
.getMd5( ) , nPassword.getSha1( ) );
return this.mapToResult( m );
}
@Override
public MailChangeData getMailChange( int accountId )
{
String sql = "SELECT * FROM users.mail_change_view WHERE id = ?";
try {
return this.dTemplate.queryForObject( sql , this.mailChangeMapper , accountId );
} catch ( EmptyResultDataAccessException e ) {
return null;
}
}
@Override
public void setLanguage( EmailAddress address , String language )
{
this.fSetLanguage.execute( address.getAddress( ) , language );
}
@Override
public boolean setPassword( Account account , Password newPassword )
{
int id = account.getId( );
String sha1 = newPassword.getSha1( );
String md5 = newPassword.getMd5( );
return (Boolean) this.fSetPassword.execute( id , sha1 , md5 ).get( "success" );
}
@Override
public int setAddress( Account account , EmailAddress nAddress )
{
return (Integer) this.fSetAddress.execute( account.getId( ) , nAddress.getAddress( ) ).get( "err_code" );
}
@Override
public void cancelAddressChange( Account account )
{
this.fCancelAddressChange.execute( account.getId( ) );
}
@Override
public int confirmAddressChange( Account account , String code )
{
Integer nv;
nv = (Integer) this.fConfirmAddressChange.execute( account.getId( ) , code ).get( "n_id" );
return ( nv == null ) ? account.getId( ) : nv.intValue( );
}
@Override
public void expireRequests( )
{
this.dTemplate.getJdbcOperations( ).execute( "SELECT users.expire_requests( )" );
}
@Override
public void setQuit( Account account , String reason )
{
this.fSetQuit.execute( account.getId( ) , reason );
}
@Override
public void cancelQuit( Account account )
{
this.fCancelQuit.execute( account.getId( ) );
}
@Override
public List< QuittingAccount > processQuits( )
{
String sql = "SELECT * FROM users.process_quit_requests( )";
return this.dTemplate.query( sql , this.quitMapper );
}
@Override
public void enterVacation( Account account )
{
this.fEnterVacation.execute( account.getId( ) );
}
@Override
public void leaveVacation( Account account )
{
this.fLeaveVacation.execute( account.getId( ) );
}
@Override
public void processVacations( )
{
this.dTemplate.getJdbcOperations( ).execute( "SELECT users.process_vacations( )" );
}
@Override
public List< AccountListEntry > listAccounts( AccountStatus status )
{
String sql = "SELECT * FROM admin.users_list";
Object[] params;
if ( status != null ) {
sql += " WHERE status = ?";
params = new Object[] {
status.toString( )
};
} else {
params = new Object[] { };
}
return this.dTemplate.query( sql , this.mAccountList , params );
}
@Override
public List< AccountListEntry > listOnlineAccounts( AccountStatus status )
{
String sql = "SELECT u.* FROM admin.users_list u INNER JOIN users.sessions s ON s.credentials_id = u.id AND s.end_type IS NULL AND s.exclusive";
Object[] params;
if ( status != null ) {
sql += " WHERE u.status = ?";
params = new Object[] {
status.toString( )
};
} else {
params = new Object[] { };
}
return this.dTemplate.query( sql , this.mAccountList , params );
}
@Override
public AccountViewEntry viewAccount( int id )
{
String sql = "SELECT * FROM admin.users_list WHERE id = ?";
try {
return this.dTemplate.queryForObject( sql , this.mAccountView , id );
} catch ( EmptyResultDataAccessException e ) {
return null;
}
}
@Override
public void giveCredits( int adminId , int accountId , int credits )
{
this.fGrantCredits.execute( adminId , accountId , credits );
}
@Override
public void deleteOldAccounts( )
{
this.dTemplate.getJdbcOperations( ).execute( "SELECT users.delete_old_accounts( )" );
}
@Override
public List< QuittingAccount > getInactivesToWarn( )
{
String sql = "SELECT * FROM users.check_inactivity_emails( )";
return this.dTemplate.query( sql , this.quitMapper );
}
@Override
public List< QuittingAccount > getInactivesToDisable( )
{
String sql = "SELECT * FROM users.check_inactivity( )";
return this.dTemplate.query( sql , this.quitMapper );
}
}

View file

@ -0,0 +1,65 @@
package com.deepclone.lw.beans.acm;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.support.TransactionTemplate;
import com.deepclone.lw.interfaces.acm.UsersDAO;
import com.deepclone.lw.interfaces.sys.Ticker;
import com.deepclone.lw.interfaces.sys.Ticker.Frequency;
public class VacationProcessorBean
implements InitializingBean , DisposableBean
{
private TransactionTemplate tTemplate;
private Ticker ticker;
private UsersDAO usersDao;
private VacationProcessorTask vacationProcessor;
@Autowired( required = true )
public void setTransactionManager( PlatformTransactionManager tManager )
{
this.tTemplate = new TransactionTemplate( tManager );
}
@Autowired( required = true )
public void setTicker( Ticker ticker )
{
this.ticker = ticker;
}
@Autowired( required = true )
public void setUsersDAO( UsersDAO usersDao )
{
this.usersDao = usersDao;
}
@Override
public void afterPropertiesSet( )
throws Exception
{
this.vacationProcessor = new VacationProcessorTask( this.tTemplate , this.usersDao );
this.ticker.registerTask( Frequency.MINUTE , "Vacation processor" , this.vacationProcessor );
}
@Override
public void destroy( )
{
this.vacationProcessor = null;
}
}

View file

@ -0,0 +1,38 @@
package com.deepclone.lw.beans.acm;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import com.deepclone.lw.interfaces.acm.UsersDAO;
class VacationProcessorTask
implements Runnable
{
private TransactionTemplate tTemplate;
private UsersDAO usersDao;
public VacationProcessorTask( TransactionTemplate tTemplate , UsersDAO usersDao )
{
this.tTemplate = tTemplate;
this.usersDao = usersDao;
}
@Override
public void run( )
{
this.tTemplate.execute( new TransactionCallbackWithoutResult( ) {
@Override
protected void doInTransactionWithoutResult( TransactionStatus status )
{
usersDao.processVacations( );
}
} );
}
}

View file

@ -0,0 +1,251 @@
package com.deepclone.lw.beans.admin;
import java.net.InetAddress;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
import com.deepclone.lw.cmd.admin.adata.AdminOverview;
import com.deepclone.lw.interfaces.admin.AdminDAO;
import com.deepclone.lw.interfaces.admin.AdminDAOException;
import com.deepclone.lw.sqld.admin.AdminConnection;
import com.deepclone.lw.sqld.admin.AdminRecord;
import com.deepclone.lw.utils.EmailAddress;
import com.deepclone.lw.utils.StoredProc;
public class AdminDAOBean
implements AdminDAO
{
private static final String sGetAdminById = "SELECT * FROM admin.admins_view WHERE administrator_id = ?";
private static final String sGetAdminByAddress = "SELECT * FROM admin.admins_view WHERE address = ?";
private static final String sGetAdminByName = "SELECT * FROM admin.admins_view WHERE lower( name ) = ?";
private static final String sListAdministrators = "SELECT * FROM admin.admins_view ORDER BY active DESC , name";
private SimpleJdbcTemplate dTemplate;
private final RowMapper< AdminRecord > mAdminRecord;
private final RowMapper< AdminOverview > mAdminOverview;
private StoredProc fCreateAdmin;
private StoredProc fLogConnection;
private StoredProc fLogDisconnection;
private StoredProc fSetPassword;
private StoredProc fResetPassword;
private StoredProc fSetPrivileges;
public AdminDAOBean( )
{
this.mAdminRecord = new RowMapper< AdminRecord >( ) {
@Override
public AdminRecord mapRow( ResultSet rs , int rowNum )
throws SQLException
{
AdminRecord admin = new AdminRecord( );
admin.setId( rs.getInt( "administrator_id" ) );
admin.setName( rs.getString( "name" ) );
admin.setPrivileges( rs.getInt( "privileges" ) );
admin.setActive( rs.getBoolean( "active" ) );
admin.setAccount( (Integer) rs.getObject( "account_id" ) );
admin.setAddress( rs.getString( "address" ) );
admin.setpMd5( rs.getString( "pass_md5" ) );
admin.setpSha1( rs.getString( "pass_sha1" ) );
admin.setPassChangeRequired( (Boolean) rs.getObject( "pass_change_required" ) );
return admin;
}
};
this.mAdminOverview = new RowMapper< AdminOverview >( ) {
@Override
public AdminOverview mapRow( ResultSet rs , int rowNum )
throws SQLException
{
AdminOverview ov = new AdminOverview( );
ov.setId( rs.getInt( "admin_id" ) );
ov.setNewMessages( rs.getLong( "new_messages" ) );
ov.setPendingNames( rs.getLong( "pending_names" ) );
ov.setPendingBans( rs.getLong( "pending_bans" ) );
ov.setPendingBugs( rs.getLong( "pending_bugs" ) );
ov.setOpenBugs( rs.getLong( "open_bugs" ) );
ov.setUpdatedBugs( rs.getLong( "updated_bugs" ) );
return ov;
}
};
}
@Autowired( required = true )
public void setDataSource( DataSource dataSource )
{
this.dTemplate = new SimpleJdbcTemplate( dataSource );
this.fCreateAdmin = new StoredProc( dataSource , "admin" , "create_admin" );
this.fCreateAdmin.addParameter( "address" , Types.VARCHAR );
this.fCreateAdmin.addParameter( "admin_name" , Types.VARCHAR );
this.fCreateAdmin.addParameter( "privileges" , Types.INTEGER );
this.fCreateAdmin.addOutput( "err_code" , Types.INTEGER );
this.fCreateAdmin.addOutput( "admin_id" , Types.INTEGER );
this.fLogConnection = new StoredProc( dataSource , "admin" , "log_connection" );
this.fLogConnection.addParameter( "admin_id" , Types.INTEGER );
this.fLogConnection.addParameter( "result" , "admin_connection_result" );
this.fLogConnection.addParameter( "ip_address" , Types.VARCHAR );
this.fLogDisconnection = new StoredProc( dataSource , "admin" , "log_disconnection" );
this.fLogDisconnection.addParameter( "admin_id" , Types.INTEGER );
this.fSetPassword = new StoredProc( dataSource , "admin" , "set_password" );
this.fSetPassword.addParameter( "admin_id" , Types.INTEGER );
this.fSetPassword.addParameter( "pass_sha1" , Types.VARCHAR );
this.fSetPassword.addParameter( "pass_md5" , Types.VARCHAR );
this.fSetPassword.addOutput( "success" , Types.BOOLEAN );
this.fResetPassword = new StoredProc( dataSource , "admin" , "reset_password" );
this.fResetPassword.addParameter( "admin_id" , Types.INTEGER );
this.fResetPassword.addParameter( "superuser_id" , Types.INTEGER );
this.fResetPassword.addOutput( "success" , Types.BOOLEAN );
this.fSetPrivileges = new StoredProc( dataSource , "admin" , "set_privileges" );
this.fSetPrivileges.addParameter( "admin_id" , Types.INTEGER );
this.fSetPrivileges.addParameter( "superuser_id" , Types.INTEGER );
this.fSetPrivileges.addParameter( "privileges" , Types.INTEGER );
this.fSetPrivileges.addOutput( "success" , Types.BOOLEAN );
}
@Override
public AdminRecord getAdmin( int id )
{
try {
return this.dTemplate.queryForObject( sGetAdminById , this.mAdminRecord , id );
} catch ( EmptyResultDataAccessException e ) {
return null;
}
}
@Override
public AdminRecord getAdmin( EmailAddress address )
{
try {
return this.dTemplate.queryForObject( sGetAdminByAddress , this.mAdminRecord , address.getAddress( ) );
} catch ( EmptyResultDataAccessException e ) {
return null;
}
}
@Override
public AdminRecord getAdmin( String name )
{
try {
return this.dTemplate.queryForObject( sGetAdminByName , this.mAdminRecord , name.toLowerCase( ) );
} catch ( EmptyResultDataAccessException e ) {
return null;
}
}
@Override
public int createAdmin( String address , String name , int privileges )
throws AdminDAOException
{
Map< String , Object > result = this.fCreateAdmin.execute( address , name , privileges );
int errCode = (Integer) result.get( "err_code" );
if ( errCode != 0 ) {
throw new AdminDAOException( errCode );
}
return (Integer) result.get( "admin_id" );
}
@Override
public void logConnectionAttempt( int id , AdminConnection status , InetAddress address )
{
this.fLogConnection.execute( id , status.toString( ) , address.getHostAddress( ) );
}
@Override
public void logDisconnection( int id )
{
this.fLogDisconnection.execute( id );
}
@Override
public boolean setPassword( int id , String sha1 , String md5 )
{
return (Boolean) this.fSetPassword.execute( id , sha1 , md5 ).get( "success" );
}
@Override
public List< AdminRecord > listAdministrators( )
{
return this.dTemplate.query( sListAdministrators , this.mAdminRecord );
}
@Override
public boolean resetPassword( int identifier , int superuser )
{
return (Boolean) this.fResetPassword.execute( identifier , superuser ).get( "success" );
}
@Override
public boolean setPrivileges( int identifier , int superuser , int privileges )
{
return (Boolean) this.fSetPrivileges.execute( identifier , superuser , privileges ).get( "success" );
}
@Override
public AdminOverview getOverview( int id )
{
String sql = "SELECT * FROM admin.overview WHERE admin_id = ?";
try {
return this.dTemplate.queryForObject( sql , this.mAdminOverview , id );
} catch ( EmptyResultDataAccessException e ) {
return null;
}
}
@Override
public List< AdminOverview > getOverviews( )
{
String sql = "SELECT * FROM admin.overview";
return this.dTemplate.query( sql , this.mAdminOverview );
}
@Override
public Timestamp isRecapTime( )
{
String sql = "SELECT * FROM admin.is_recap_time( )";
RowMapper< Timestamp > mapper = new RowMapper< Timestamp >( ) {
@Override
public Timestamp mapRow( ResultSet rs , int rowNum )
throws SQLException
{
return rs.getTimestamp( 1 );
}
};
return this.dTemplate.queryForObject( sql , mapper );
}
}

View file

@ -0,0 +1,78 @@
package com.deepclone.lw.beans.admin;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.support.TransactionTemplate;
import com.deepclone.lw.interfaces.admin.AdminDAO;
import com.deepclone.lw.interfaces.eventlog.LogReader;
import com.deepclone.lw.interfaces.mailer.Mailer;
import com.deepclone.lw.interfaces.sys.Ticker;
import com.deepclone.lw.interfaces.sys.Ticker.Frequency;
public class AdminRecapBean
implements InitializingBean , DisposableBean
{
private AdminRecapTask task;
private TransactionTemplate tTemplate;
private Ticker ticker;
private Mailer mailer;
private AdminDAO adminDao;
private LogReader logReader;
@Autowired( required = true )
public void setTransactionManager( PlatformTransactionManager tManager )
{
this.tTemplate = new TransactionTemplate( tManager );
}
@Autowired( required = true )
public void setTicker( Ticker ticker )
{
this.ticker = ticker;
}
@Autowired( required = true )
public void setMailer( Mailer mailer )
{
this.mailer = mailer;
}
@Autowired( required = true )
public void setAdminDao( AdminDAO adminDao )
{
this.adminDao = adminDao;
}
@Autowired( required = true )
public void setLogReader( LogReader logReader )
{
this.logReader = logReader;
}
@Override
public void afterPropertiesSet( )
{
this.task = new AdminRecapTask( this.tTemplate , this.mailer , this.adminDao , this.logReader );
this.ticker.registerTask( Frequency.LOW , "Admin recap task" , this.task );
}
@Override
public void destroy( )
{
this.task = null;
}
}

View file

@ -0,0 +1,162 @@
package com.deepclone.lw.beans.admin;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import com.deepclone.lw.cmd.admin.adata.AdminOverview;
import com.deepclone.lw.cmd.admin.adata.Privileges;
import com.deepclone.lw.cmd.admin.logs.LogEntry;
import com.deepclone.lw.interfaces.admin.AdminDAO;
import com.deepclone.lw.interfaces.eventlog.LogReader;
import com.deepclone.lw.interfaces.mailer.MailData;
import com.deepclone.lw.interfaces.mailer.Mailer;
import com.deepclone.lw.sqld.admin.AdminRecord;
public class AdminRecapTask
implements Runnable
{
private final TransactionTemplate tTemplate;
private final Mailer mailer;
private final AdminDAO adminDao;
private final LogReader logReader;
private Timestamp isTime;
private List< AdminRecord > admins;
private final Map< Integer , AdminOverview > overviews = new HashMap< Integer , AdminOverview >( );
private List< LogEntry > logs;
public AdminRecapTask( TransactionTemplate tTemplate , Mailer mailer , AdminDAO adminDao , LogReader logReader )
{
this.tTemplate = tTemplate;
this.mailer = mailer;
this.adminDao = adminDao;
this.logReader = logReader;
}
@Override
public void run( )
{
this.tTemplate.execute( new TransactionCallbackWithoutResult( ) {
@Override
protected void doInTransactionWithoutResult( TransactionStatus status )
{
checkRecap( );
}
} );
if ( this.isTime == null ) {
return;
}
String logs = this.buildLogsString( );
for ( AdminRecord admin : this.admins ) {
if ( !admin.isActive( ) ) {
continue;
}
String mailContents = this.buildMailContents( admin , logs );
if ( "".equals( mailContents ) ) {
continue;
}
MailData mail;
try {
mail = this.mailer.createMail( "en" , "adminRecapMail" , admin.getAddress( ) );
mail.setData( "contents" , mailContents );
mail.queue( );
} catch ( Exception e ) {
continue;
}
}
}
private String buildMailContents( AdminRecord admin , String logs )
{
AdminOverview overview = this.overviews.get( admin.getId( ) );
if ( overview == null ) {
return "";
}
StringBuilder mail = new StringBuilder( );
if ( overview.getNewMessages( ) > 0 ) {
mail.append( "Unread messages: " ).append( overview.getNewMessages( ) ).append( "\n" );
}
int privs = admin.getPrivileges( );
if ( Privileges.NAME.hasPrivilege( privs ) && overview.getPendingNames( ) > 0 ) {
mail.append( "Unvalidated map names: " ).append( overview.getPendingNames( ) ).append( "\n" );
}
if ( Privileges.BANH.hasPrivilege( privs ) && overview.getPendingBans( ) > 0 ) {
mail.append( "Pending ban requests: " ).append( overview.getPendingBans( ) ).append( "\n" );
}
if ( Privileges.BUGT.hasPrivilege( privs ) ) {
boolean showBugs = false;
if ( overview.getPendingBugs( ) > 0 ) {
mail.append( "Bug reports pending validation: " ).append( overview.getPendingBugs( ) ).append( "\n" );
showBugs = true;
}
if ( overview.getUpdatedBugs( ) > 0 ) {
mail.append( "Updated bug reports: " ).append( overview.getUpdatedBugs( ) ).append( "\n" );
showBugs = true;
}
if ( showBugs && overview.getOpenBugs( ) > 0 ) {
mail.append( "Open bug reports: " ).append( overview.getOpenBugs( ) ).append( "\n" );
}
}
if ( !"".equals( logs ) && Privileges.LOGS.hasPrivilege( privs ) ) {
mail.append( "\n" ).append( logs );
}
return mail.toString( );
}
private String buildLogsString( )
{
if ( this.logs.isEmpty( ) ) {
return "";
}
StringBuilder builder = new StringBuilder( ).append( "Administrative actions log\n\n" );
SimpleDateFormat dfmt = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" );
for ( LogEntry entry : this.logs ) {
builder.append( dfmt.format( entry.getTimestamp( ) ) );
builder.append( " - " ).append( entry.getLevel( ).toString( ) );
builder.append( " - " ).append( entry.getAbout( ) );
builder.append( " - " ).append( entry.getEntry( ) );
builder.append( "\n" );
}
return builder.toString( );
}
private void checkRecap( )
{
this.isTime = this.adminDao.isRecapTime( );
if ( this.isTime == null ) {
return;
}
this.admins = this.adminDao.listAdministrators( );
for ( AdminOverview ov : this.adminDao.getOverviews( ) ) {
this.overviews.put( ov.getId( ) , ov );
}
this.logs = this.logReader.getAdminLogSince( this.isTime );
}
}

View file

@ -0,0 +1,356 @@
package com.deepclone.lw.beans.admin;
import java.net.InetAddress;
import java.util.List;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import com.deepclone.lw.cmd.ObjectNameError;
import com.deepclone.lw.cmd.admin.AdminOverviewResponse;
import com.deepclone.lw.cmd.admin.adata.AdminOverview;
import com.deepclone.lw.cmd.admin.adata.Administrator;
import com.deepclone.lw.cmd.admin.adata.Privileges;
import com.deepclone.lw.cmd.admin.bans.BanRequest;
import com.deepclone.lw.cmd.admin.bans.BanType;
import com.deepclone.lw.cmd.admin.bans.BansSummaryResponse;
import com.deepclone.lw.cmd.admin.bans.ListBansResponse;
import com.deepclone.lw.cmd.admin.bans.RequestBanResponse;
import com.deepclone.lw.cmd.admin.logs.LogLevel;
import com.deepclone.lw.cmd.admin.su.AddAdministratorResponse;
import com.deepclone.lw.cmd.admin.su.AddAdministratorResponse.AddressError;
import com.deepclone.lw.interfaces.acm.PasswordProhibitedException;
import com.deepclone.lw.interfaces.admin.AdminDAO;
import com.deepclone.lw.interfaces.admin.AdminDAOException;
import com.deepclone.lw.interfaces.admin.Administration;
import com.deepclone.lw.interfaces.admin.BanMailData;
import com.deepclone.lw.interfaces.admin.BansDAO;
import com.deepclone.lw.interfaces.admin.IpBan;
import com.deepclone.lw.interfaces.eventlog.Logger;
import com.deepclone.lw.interfaces.eventlog.SystemLogger;
import com.deepclone.lw.interfaces.mailer.MailData;
import com.deepclone.lw.interfaces.mailer.Mailer;
import com.deepclone.lw.sqld.admin.AdminConnection;
import com.deepclone.lw.sqld.admin.AdminRecord;
import com.deepclone.lw.utils.DigestHelper;
import com.deepclone.lw.utils.EmailAddress;
import com.deepclone.lw.utils.Password;
@Transactional
public class AdministrationBean
implements Administration
{
private SystemLogger sysLog;
private AdminDAO adminDao;
private IpBan ipBan;
private BansDAO bansDao;
private Mailer mailer;
@Autowired( required = true )
public void setLogger( Logger logger )
{
this.sysLog = logger.getSystemLogger( "Administration" );
}
@Autowired( required = true )
public void setAdminDao( AdminDAO adminDao )
{
this.adminDao = adminDao;
}
@Autowired( required = true )
public void setIpBan( IpBan ipBan )
{
this.ipBan = ipBan;
}
@Autowired( required = true )
public void setBansDao( BansDAO bansDao )
{
this.bansDao = bansDao;
}
@Autowired( required = true )
public void setMailer( Mailer mailer )
{
this.mailer = mailer;
}
@Override
public AdminRecord getAdmin( int id )
{
return this.adminDao.getAdmin( id );
}
@Override
public AdminRecord login( EmailAddress address , String challenge , String sha1Hash , String md5Hash ,
InetAddress ipAddress )
{
// Check IP ban
if ( this.ipBan.isBanned( ipAddress ) ) {
return null;
}
// Find admin record
AdminRecord record = this.adminDao.getAdmin( address );
if ( record == null ) {
this.ipBan.increaseBanCounter( ipAddress );
this.sysLog.log( LogLevel.WARNING ,
"failed login attempt from unknown address '" + address.getAddress( ) + "'" ).flush( );
return null;
}
// Make sure the administrator is active
if ( !record.isActive( ) ) {
this.ipBan.increaseBanCounter( ipAddress );
this.adminDao.logConnectionAttempt( record.getId( ) , AdminConnection.INACTIVE , ipAddress );
return null;
}
// Check password
String eSha1 = DigestHelper.digest( "sha-1" , challenge + " " + record.getpSha1( ) );
String eMd5 = DigestHelper.digest( "md5" , challenge + " " + record.getpMd5( ) );
if ( eSha1.equals( sha1Hash ) && eMd5.equals( md5Hash ) ) {
this.adminDao.logConnectionAttempt( record.getId( ) , AdminConnection.SUCCESS , ipAddress );
return record;
}
this.ipBan.increaseBanCounter( ipAddress );
this.adminDao.logConnectionAttempt( record.getId( ) , AdminConnection.PASSWORD , ipAddress );
return null;
}
@Override
public void logout( int adminId )
{
this.adminDao.logDisconnection( adminId );
}
@Override
public boolean setPassword( int id , String challenge , String sha1Auth , String md5Auth , Password password )
throws PasswordProhibitedException
{
AdminRecord admin = this.getAdmin( id );
// Check challenge response
String eSha1 = DigestHelper.digest( "sha-1" , challenge + " " + admin.getpSha1( ) );
String eMd5 = DigestHelper.digest( "md5" , challenge + " " + admin.getpMd5( ) );
if ( ! ( eSha1.equals( sha1Auth ) && eMd5.equals( md5Auth ) ) ) {
return false;
}
// Try setting the password
if ( !this.adminDao.setPassword( id , password.getSha1( ) , password.getMd5( ) ) ) {
throw new PasswordProhibitedException( );
}
return true;
}
@Override
public List< AdminRecord > listAdministrators( )
{
return this.adminDao.listAdministrators( );
}
@Override
public AddAdministratorResponse createAdmin( Administrator creator , String address , String name , int privileges )
{
int errCode;
try {
this.adminDao.createAdmin( address , name , privileges );
return new AddAdministratorResponse( creator , false );
} catch ( AdminDAOException e ) {
errCode = e.getErrorCode( );
}
AddressError aError;
ObjectNameError nError;
switch ( errCode ) {
case 1:
aError = AddressError.NOT_FOUND;
nError = null;
break;
case 2:
aError = AddressError.STATUS;
nError = null;
break;
case 3:
aError = null;
nError = ObjectNameError.UNAVAILABLE;
break;
case 4:
aError = AddressError.ALREADY_ADMIN;
nError = null;
break;
default:
throw new RuntimeException( "unknown error code " + errCode );
}
return new AddAdministratorResponse( creator , aError , address , nError , name , false , privileges );
}
@Override
public AdminRecord resetPassword( Administrator admin , int identifier )
{
if ( this.adminDao.resetPassword( identifier , admin.getId( ) ) ) {
return this.adminDao.getAdmin( identifier );
}
return null;
}
@Override
public AdminRecord setPrivileges( Administrator admin , int identifier , Set< Privileges > privileges )
{
int privs = 0;
for ( Privileges p : privileges ) {
privs = p.grant( privs );
}
if ( this.adminDao.setPrivileges( identifier , admin.getId( ) , privs ) ) {
return this.adminDao.getAdmin( identifier );
}
return null;
}
@Override
public BansSummaryResponse getBansSummary( Administrator admin )
{
return new BansSummaryResponse( admin , this.bansDao.getSummary( ) );
}
@Override
public ListBansResponse getBans( Administrator admin , BanType type )
{
List< BanRequest > bans;
switch ( type ) {
case PENDING:
bans = this.bansDao.getPending( );
break;
case ARCHIVED:
bans = this.bansDao.getArchived( );
break;
case VALIDATED:
bans = this.bansDao.getActive( );
break;
default:
throw new RuntimeException( "unknown ban type " + type );
}
return new ListBansResponse( admin , type , bans );
}
@Override
public RequestBanResponse requestBan( Administrator admin , String user , boolean empire , String reason )
{
int errCode;
if ( empire ) {
errCode = this.bansDao.requestBan( admin.getId( ) , user , reason );
} else {
EmailAddress address = new EmailAddress( user );
if ( !address.isValid( ) ) {
errCode = 1;
} else {
errCode = this.bansDao.requestBan( admin.getId( ) , address , reason );
}
}
if ( errCode == 0 ) {
return new RequestBanResponse( admin , false );
}
RequestBanResponse.Error error;
switch ( errCode ) {
case 1:
error = RequestBanResponse.Error.NOT_FOUND;
break;
case 2:
error = RequestBanResponse.Error.BANNED;
break;
default:
throw new RuntimeException( "unknown error code " + errCode );
}
return new RequestBanResponse( admin , error , user , empire , reason );
}
@Override
public void rejectBan( Administrator admin , int id , String reason )
{
this.bansDao.rejectBan( admin.getId( ) , id , reason );
}
@Override
public void confirmBan( Administrator admin , int id )
{
BanMailData result = this.bansDao.validateBan( admin.getId( ) , id );
if ( result == null ) {
return;
}
try {
MailData mail = this.mailer.createMail( result.language , "bannedMail" , result.address );
mail.setData( "reason" , result.reason );
mail.queue( );
} catch ( Exception e ) {
throw new RuntimeException( e );
}
}
@Override
public void liftBan( Administrator admin , int id )
{
BanMailData result = this.bansDao.liftBan( admin.getId( ) , id );
if ( result == null ) {
return;
}
try {
MailData mail = this.mailer.createMail( result.language , "banLiftedMail" , result.address );
mail.queue( );
} catch ( Exception e ) {
throw new RuntimeException( e );
}
}
@Override
public AdminOverviewResponse getOverview( Administrator admin )
{
AdminOverview overview = this.adminDao.getOverview( admin.getId( ) );
if ( !admin.hasPrivilege( Privileges.NAME ) ) {
overview.setPendingNames( null );
}
if ( !admin.hasPrivilege( Privileges.BANH ) ) {
overview.setPendingBans( null );
}
if ( !admin.hasPrivilege( Privileges.BUGT ) ) {
overview.setPendingBugs( null );
overview.setOpenBugs( null );
overview.setUpdatedBugs( null );
}
return new AdminOverviewResponse( admin , overview );
}
}

View file

@ -0,0 +1,284 @@
package com.deepclone.lw.beans.admin;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
import com.deepclone.lw.cmd.admin.bans.ArchivedBanRequest;
import com.deepclone.lw.cmd.admin.bans.BanRequest;
import com.deepclone.lw.cmd.admin.bans.BanType;
import com.deepclone.lw.cmd.admin.bans.SummaryEntry;
import com.deepclone.lw.cmd.admin.bans.ValidatedBanRequest;
import com.deepclone.lw.interfaces.admin.BanMailData;
import com.deepclone.lw.interfaces.admin.BansDAO;
import com.deepclone.lw.utils.EmailAddress;
import com.deepclone.lw.utils.StoredProc;
public class BansDAOBean
implements BansDAO
{
private static final String sGetPending = "SELECT * FROM admin.pending_bans ORDER BY requested DESC";
private static final String sGetArchived = "SELECT * FROM admin.cancelled_bans ORDER BY updated DESC";
private static final String sGetValidated = "SELECT * FROM admin.active_bans ORDER BY updated DESC";
private static final String sGetBan = "SELECT * FROM admin.active_bans WHERE account_mail = ?";
private static abstract class BanRequestMapper< T extends BanRequest >
implements RowMapper< T >
{
protected void getCommonData( BanRequest br , ResultSet rs )
throws SQLException
{
br.setId( rs.getInt( "id" ) );
br.setRequestedById( rs.getInt( "requested_by_id" ) );
br.setRequestedByName( rs.getString( "requested_by_name" ) );
br.setAccountId( rs.getInt( "account_id" ) );
br.setAccountMail( rs.getString( "account_mail" ) );
br.setTimestamp( rs.getTimestamp( "requested" ) );
br.setReason( rs.getString( "reason" ) );
}
}
private SimpleJdbcTemplate dTemplate;
private final BanRequestMapper< BanRequest > mPending;
private final BanRequestMapper< BanRequest > mArchived;
private final BanRequestMapper< BanRequest > mValidated;
private final RowMapper< Boolean > mBoolean;
private StoredProc fRequestBanAddress;
private StoredProc fRequestBanEmpire;
private StoredProc fRejectBan;
private StoredProc fValidateBan;
private StoredProc fLiftBan;
public BansDAOBean( )
{
this.mPending = new BanRequestMapper< BanRequest >( ) {
@Override
public BanRequest mapRow( ResultSet rs , int rowNum )
throws SQLException
{
BanRequest br = new BanRequest( );
this.getCommonData( br , rs );
return br;
}
};
this.mArchived = new BanRequestMapper< BanRequest >( ) {
@Override
public BanRequest mapRow( ResultSet rs , int rowNum )
throws SQLException
{
ArchivedBanRequest br = new ArchivedBanRequest( );
this.getCommonData( br , rs );
br.setUpdate( rs.getTimestamp( "updated" ) );
br.setExpired( rs.getBoolean( "expired" ) );
if ( !br.isExpired( ) ) {
br.setRejectedById( rs.getInt( "rejected_by_id" ) );
br.setRejectedByName( rs.getString( "rejected_by_name" ) );
br.setRejectionReason( rs.getString( "rejection_reason" ) );
}
return br;
}
};
this.mValidated = new BanRequestMapper< BanRequest >( ) {
@Override
public BanRequest mapRow( ResultSet rs , int rowNum )
throws SQLException
{
ValidatedBanRequest br = new ValidatedBanRequest( );
this.getCommonData( br , rs );
br.setUpdate( rs.getTimestamp( "updated" ) );
br.setRedeemable( rs.getBoolean( "redeemable" ) );
br.setValidatedById( rs.getInt( "validated_by_id" ) );
br.setValidatedByName( rs.getString( "validated_by_name" ) );
return br;
}
};
this.mBoolean = new RowMapper< Boolean >( ) {
@Override
public Boolean mapRow( ResultSet rs , int rowNum )
throws SQLException
{
return rs.getBoolean( 1 );
}
};
}
@Autowired( required = true )
public void setDataSource( DataSource dataSource )
{
this.dTemplate = new SimpleJdbcTemplate( dataSource );
this.fRequestBanAddress = new StoredProc( dataSource , "admin" , "request_ban_on_address" );
this.fRequestBanAddress.addParameter( "admin_id" , Types.INTEGER );
this.fRequestBanAddress.addParameter( "user_address" , Types.VARCHAR );
this.fRequestBanAddress.addParameter( "reason" , Types.VARCHAR );
this.fRequestBanAddress.addOutput( "err_code" , Types.INTEGER );
this.fRequestBanEmpire = new StoredProc( dataSource , "admin" , "request_ban_on_empire" );
this.fRequestBanEmpire.addParameter( "admin_id" , Types.INTEGER );
this.fRequestBanEmpire.addParameter( "user_address" , Types.VARCHAR );
this.fRequestBanEmpire.addParameter( "reason" , Types.VARCHAR );
this.fRequestBanEmpire.addOutput( "err_code" , Types.INTEGER );
this.fRejectBan = new StoredProc( dataSource , "admin" , "reject_ban_request" );
this.fRejectBan.addParameter( "admin_id" , Types.INTEGER );
this.fRejectBan.addParameter( "request_id" , Types.INTEGER );
this.fRejectBan.addParameter( "reason" , Types.VARCHAR );
this.fValidateBan = new StoredProc( dataSource , "admin" , "confirm_ban_request" );
this.fValidateBan.addParameter( "admin_id" , Types.INTEGER );
this.fValidateBan.addParameter( "request_id" , Types.INTEGER );
this.fValidateBan.addOutput( "success" , Types.BOOLEAN );
this.fValidateBan.addOutput( "addr" , Types.VARCHAR );
this.fValidateBan.addOutput( "lang" , Types.VARCHAR );
this.fValidateBan.addOutput( "r_txt" , Types.VARCHAR );
this.fLiftBan = new StoredProc( dataSource , "admin" , "lift_ban" );
this.fLiftBan.addParameter( "admin_id" , Types.INTEGER );
this.fLiftBan.addParameter( "request_id" , Types.INTEGER );
this.fLiftBan.addOutput( "success" , Types.BOOLEAN );
this.fLiftBan.addOutput( "addr" , Types.VARCHAR );
this.fLiftBan.addOutput( "lang" , Types.VARCHAR );
}
@Override
public List< SummaryEntry > getSummary( )
{
List< SummaryEntry > result = new ArrayList< SummaryEntry >( 3 );
final String names[] = {
"pending" , "cancelled" , "active"
};
for ( int i = 0 ; i < 3 ; i++ ) {
long count = this.dTemplate.queryForLong( "SELECT count(*) FROM admin." + names[ i ] + "_bans" );
result.add( new SummaryEntry( BanType.values( )[ i ] , count ) );
}
return result;
}
@Override
public List< BanRequest > getPending( )
{
return this.dTemplate.query( sGetPending , this.mPending );
}
@Override
public List< BanRequest > getArchived( )
{
return this.dTemplate.query( sGetArchived , this.mArchived );
}
@Override
public List< BanRequest > getActive( )
{
return this.dTemplate.query( sGetValidated , this.mValidated );
}
private int requestBan( StoredProc fRequestBan , int administrator , String address , String reason )
{
return (Integer) fRequestBan.execute( administrator , address , reason ).get( "err_code" );
}
@Override
public int requestBan( int administrator , EmailAddress address , String reason )
{
return this.requestBan( this.fRequestBanAddress , administrator , address.getAddress( ) , reason );
}
@Override
public int requestBan( int administrator , String empire , String reason )
{
return this.requestBan( this.fRequestBanEmpire , administrator , empire , reason );
}
@Override
public void rejectBan( int administrator , int requestId , String reason )
{
this.fRejectBan.execute( administrator , requestId , reason );
}
@Override
public BanMailData validateBan( int administrator , int requestId )
{
Map< String , Object > result = this.fValidateBan.execute( administrator , requestId );
boolean success = (Boolean) result.get( "success" );
if ( !success ) {
return null;
}
return new BanMailData( (String) result.get( "addr" ) , (String) result.get( "lang" ) , (String) result
.get( "r_txt" ) );
}
@Override
public BanMailData liftBan( int administrator , int requestId )
{
Map< String , Object > result = this.fLiftBan.execute( administrator , requestId );
boolean success = (Boolean) result.get( "success" );
if ( !success ) {
return null;
}
return new BanMailData( (String) result.get( "addr" ) , (String) result.get( "lang" ) );
}
@Override
public void expireBanRequests( )
{
this.dTemplate.getJdbcOperations( ).execute( "SELECT admin.expire_ban_requests( )" );
}
@Override
public void expireWarnings( )
{
this.dTemplate.getJdbcOperations( ).execute( "SELECT admin.expire_warnings( )" );
}
@Override
public boolean finaliseBan( )
{
String sql = "SELECT admin.delete_banned_empires( )";
return this.dTemplate.queryForObject( sql , this.mBoolean );
}
@Override
public ValidatedBanRequest getActiveBan( EmailAddress address )
{
try {
return (ValidatedBanRequest) this.dTemplate.queryForObject( sGetBan , this.mValidated , address
.getAddress( ) );
} catch ( EmptyResultDataAccessException e ) {
return null;
}
}
}

View file

@ -0,0 +1,62 @@
package com.deepclone.lw.beans.admin;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.support.TransactionTemplate;
import com.deepclone.lw.interfaces.admin.BansDAO;
import com.deepclone.lw.interfaces.sys.Ticker;
import com.deepclone.lw.interfaces.sys.Ticker.Frequency;
public class BansProcessorBean
implements InitializingBean , DisposableBean
{
private Ticker ticker;
private BansProcessorTask task;
private TransactionTemplate tTemplate;
private BansDAO bansDao;
@Autowired( required = true )
public void setTicker( Ticker ticker )
{
this.ticker = ticker;
}
@Autowired( required = true )
public void setTransactionManager( PlatformTransactionManager tManager )
{
this.tTemplate = new TransactionTemplate( tManager );
}
@Autowired( required = true )
public void setBansDao( BansDAO bansDao )
{
this.bansDao = bansDao;
}
@Override
public void afterPropertiesSet( )
throws Exception
{
this.task = new BansProcessorTask( this.tTemplate , this.bansDao );
this.ticker.registerTask( Frequency.LOW , "Bans processor" , this.task );
}
@Override
public void destroy( )
throws Exception
{
this.task = null;
}
}

View file

@ -0,0 +1,62 @@
package com.deepclone.lw.beans.admin;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import com.deepclone.lw.interfaces.admin.BansDAO;
class BansProcessorTask
implements Runnable
{
private final TransactionTemplate tTemplate;
private final BansDAO bansDao;
public BansProcessorTask( TransactionTemplate tTemplate , BansDAO bansDao )
{
this.tTemplate = tTemplate;
this.bansDao = bansDao;
}
@Override
public void run( )
{
this.expire( );
while ( this.finaliseBans( ) ) {
// EMPTY
}
}
private boolean finaliseBans( )
{
return this.tTemplate.execute( new TransactionCallback< Boolean >( ) {
@Override
public Boolean doInTransaction( TransactionStatus status )
{
return bansDao.finaliseBan( );
}
} );
}
private void expire( )
{
this.tTemplate.execute( new TransactionCallbackWithoutResult( ) {
@Override
protected void doInTransactionWithoutResult( TransactionStatus status )
{
bansDao.expireBanRequests( );
bansDao.expireWarnings( );
}
} );
}
}

View file

@ -0,0 +1,87 @@
package com.deepclone.lw.beans.admin;
import java.net.InetAddress;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import com.deepclone.lw.interfaces.admin.IpBan;
/**
* The IP Ban bean specifies a private map container to hold IP Address ban entries. It also
* provides a public method to check whether a specified IP address is banned and a public method to
* increaes the counter of a given IP address.
*
* @author tseeker
*
*/
public class IpBanBean
implements IpBan
{
/**
* Static class with the date the ban was last increased and the counter of times increased.
*/
private static class BanEntry
{
public Date lastIncrease = new Date( );
public int counter = 1;
}
/** Private HashMap containing current IP addresses and their associated BanEntry's */
private final Map< InetAddress , BanEntry > entries = new HashMap< InetAddress , BanEntry >( );
/**
* Checks if an IP address is banned. An address is banned if an entry already exists for it, if
* the ban's duration has been reset in the last hour and the IP address's counter has been
* increased 3 or more times. If the ban is more than an hour old it is removed.
*/
@Override
public boolean isBanned( InetAddress address )
{
synchronized ( this.entries ) {
BanEntry entry = this.entries.get( address );
if ( entry == null ) {
return false;
}
if ( entry.lastIncrease.before( new Date( new Date( ).getTime( ) - 60 * 60 * 1000 ) ) ) {
this.entries.remove( address );
return false;
}
if ( entry.counter < 3 ) {
return false;
}
entry.lastIncrease = new Date( );
return true;
}
}
/**
* If the given IP address does not already have an entry associated with it, one is created for
* it. If it does, the entries counter is increased by 1.
*/
@Override
public void increaseBanCounter( InetAddress address )
{
synchronized ( this.entries ) {
BanEntry entry = this.entries.get( address );
if ( entry == null ) {
entry = new BanEntry( );
this.entries.put( address , entry );
return;
}
entry.counter++;
entry.lastIncrease = new Date( );
}
}
}

View file

@ -0,0 +1,28 @@
package com.deepclone.lw.beans.prefs;
class BoolPreferenceType
extends PreferenceTypeImpl< Boolean >
{
public BoolPreferenceType( )
{
super( Boolean.class );
}
@Override
public String convert( Object value )
{
Boolean v = (Boolean) value;
return ( v != null && v ) ? "1" : "0";
}
@Override
public Boolean valueOf( String dbValue , Class< Boolean > type )
{
return "1".equals( dbValue );
}
}

View file

@ -0,0 +1,79 @@
package com.deepclone.lw.beans.prefs;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import com.deepclone.lw.cmd.player.gdata.MailPreference;
import com.deepclone.lw.cmd.player.gdata.MapSize;
import com.deepclone.lw.interfaces.prefs.PreferenceDefinitions;
public class DefaultPreferencesBean
implements InitializingBean
{
private PreferenceDefinitions pDefs;
private PreferenceTypesRegistryBean registry;
@Autowired( required = true )
public void setTypesRegistry( PreferenceTypesRegistryBean registry )
{
this.registry = registry;
}
@Autowired( required = true )
public void setPreferenceDefinitions( PreferenceDefinitions preferenceDefinitions )
{
this.pDefs = preferenceDefinitions;
}
@Override
public void afterPropertiesSet( )
throws Exception
{
this.createTypes( );
this.pDefs.registerGroup( "display" , "pgDisplay" );
this.pDefs.registerPreference( "useRLTime" , "display" , "pUseRLTime" , "pUseRLTimeDescription" ,
(Boolean) false );
this.pDefs.registerGroup( "map" , "pgMap" );
this.pDefs.registerPreference( "mapX" , "map" , "pMapX" , "pMapXDescription" , (Integer) 0 );
this.pDefs.registerPreference( "mapY" , "map" , "pMapY" , "pMapYDescription" , (Integer) 0 );
this.pDefs.registerPreference( "mapSize" , "map" , "pMapSize" , "pMapSizeDescription" , MapSize.MEDIUM );
this.pDefs.registerGroup( "mail" , "pgMail" );
this.pDefs.registerPreference( "mailOnPM" , "mail" , "pMailOnPM" , "pMailOnPMDescription" ,
MailPreference.INSTANT );
this.pDefs.registerPreference( "mailOnAlliance" , "mail" , "pMailOnAlliance" , "pMailOnAllianceDescription" ,
MailPreference.DAILY_RECAP );
this.pDefs.registerPreference( "mailOnIM" , "mail" , "pMailOnIM" , "pMailOnIMDescription" ,
MailPreference.DAILY_RECAP );
this.pDefs.registerPreference( "mailOnAdmin" , "mail" , "pMailOnAdmin" , "pMailOnAdminDescription" ,
MailPreference.INSTANT );
}
private void createTypes( )
{
EnumPreferenceType< MapSize > mapSizeType;
mapSizeType = new EnumPreferenceType< MapSize >( MapSize.class );
mapSizeType.setTranslation( MapSize.SMALL , "mapSizeSmall" );
mapSizeType.setTranslation( MapSize.MEDIUM , "mapSizeMedium" );
mapSizeType.setTranslation( MapSize.LARGE , "mapSizeLarge" );
this.registry.register( mapSizeType );
EnumPreferenceType< MailPreference > mailPrefType;
mailPrefType = new EnumPreferenceType< MailPreference >( MailPreference.class );
mailPrefType.setTranslation( MailPreference.NO_MAIL , "mailPrefNo" );
mailPrefType.setTranslation( MailPreference.DAILY_RECAP , "mailPrefRecap" );
mailPrefType.setTranslation( MailPreference.INSTANT , "mailPrefInstant" );
this.registry.register( mailPrefType );
}
}

View file

@ -0,0 +1,63 @@
package com.deepclone.lw.beans.prefs;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
public class EnumPreferenceType< T >
extends PreferenceTypeImpl< T >
{
private SortedMap< T , String > choices = new TreeMap< T , String >( );
public EnumPreferenceType( Class< T > type )
{
super( type );
if ( !type.isEnum( ) ) {
throw new IllegalArgumentException( "Enumerated type expected" );
}
}
@Override
public Map< String , String > getChoices( )
{
Map< String , String > r = new LinkedHashMap< String , String >( );
for ( Map.Entry< T , String > entry : this.choices.entrySet( ) ) {
r.put( this.convert( entry.getKey( ) ) , entry.getValue( ) );
}
return r;
}
public void setTranslation( T value , String textId )
{
this.choices.put( value , textId );
}
@Override
@SuppressWarnings( "unchecked" )
public String convert( Object value )
{
return ( (T) value ).toString( );
}
@SuppressWarnings( "unchecked" )
@Override
public T valueOf( String dbValue , Class< T > type )
{
try {
return (T) type.getMethod( "valueOf" , String.class ).invoke( null , dbValue );
} catch ( Exception e ) {
throw new RuntimeException( e );
}
}
}

View file

@ -0,0 +1,31 @@
package com.deepclone.lw.beans.prefs;
class IntPreferenceType
extends PreferenceTypeImpl< Integer >
{
public IntPreferenceType( )
{
super( Integer.class );
}
@Override
public String convert( Object value )
{
return ( value == null ) ? "0" : ( (Integer) value ).toString( );
}
@Override
public Integer valueOf( String dbValue , Class< Integer > type )
{
try {
return Integer.parseInt( dbValue );
} catch ( NumberFormatException e ) {
return null;
}
}
}

View file

@ -0,0 +1,278 @@
package com.deepclone.lw.beans.prefs;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
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.annotation.Transactional;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
import com.deepclone.lw.cmd.admin.adata.Administrator;
import com.deepclone.lw.cmd.admin.logs.LogLevel;
import com.deepclone.lw.cmd.player.gdata.account.PrefCategory;
import com.deepclone.lw.cmd.player.gdata.account.PrefChoice;
import com.deepclone.lw.cmd.player.gdata.account.PrefType;
import com.deepclone.lw.cmd.player.gdata.account.PrefValue;
import com.deepclone.lw.interfaces.eventlog.Logger;
import com.deepclone.lw.interfaces.eventlog.SystemLogger;
import com.deepclone.lw.interfaces.i18n.TranslationException;
import com.deepclone.lw.interfaces.i18n.Translator;
import com.deepclone.lw.interfaces.prefs.PreferenceDefinitionException;
import com.deepclone.lw.interfaces.prefs.PreferenceDefinitions;
import com.deepclone.lw.interfaces.prefs.PreferenceType;
import com.deepclone.lw.interfaces.prefs.PreferenceTypesRegistry;
import com.deepclone.lw.utils.StoredProc;
public class PreferenceDefinitionsBean
implements PreferenceDefinitions
{
private static class PrefDefRecord
{
final String groupName;
final String groupDisplay;
final String name;
final String dName;
final String dDescription;
final String type;
final String value;
public PrefDefRecord( ResultSet rs )
throws SQLException
{
this.groupName = rs.getString( "group_name" );
this.groupDisplay = rs.getString( "group_display" );
this.name = rs.getString( "name" );
this.dName = rs.getString( "d_name" );
this.dDescription = rs.getString( "d_desc" );
this.type = rs.getString( "java_type" );
this.value = rs.getString( "default_value" );
}
}
private TransactionTemplate tTemplate;
private PreferenceTypesRegistry registry;
private SystemLogger logger;
private Translator translator;
private SimpleJdbcTemplate dTemplate;
private StoredProc uocGroup;
private StoredProc uocDef;
private StoredProc fSetDefault;
private final RowMapper< PrefDefRecord > mPrefDef;
public PreferenceDefinitionsBean( )
{
this.mPrefDef = new RowMapper< PrefDefRecord >( ) {
@Override
public PrefDefRecord mapRow( ResultSet rs , int rowNum )
throws SQLException
{
return new PrefDefRecord( rs );
}
};
}
@Autowired( required = true )
public void setDataSource( DataSource dataSource )
{
this.dTemplate = new SimpleJdbcTemplate( dataSource );
this.uocGroup = new StoredProc( dataSource , "defs" , "uoc_preference_group" );
this.uocGroup.addParameter( "name" , Types.VARCHAR );
this.uocGroup.addParameter( "display" , Types.VARCHAR );
this.uocGroup.addOutput( "success" , Types.BOOLEAN );
this.uocDef = new StoredProc( dataSource , "defs" , "uoc_preference" );
this.uocDef.addParameter( "g_name" , Types.VARCHAR );
this.uocDef.addParameter( "p_name" , Types.VARCHAR );
this.uocDef.addParameter( "d_name" , Types.VARCHAR );
this.uocDef.addParameter( "d_desc" , Types.VARCHAR );
this.uocDef.addParameter( "j_type" , Types.VARCHAR );
this.uocDef.addParameter( "d_val" , Types.VARCHAR );
this.uocDef.addOutput( "err_code" , Types.INTEGER );
this.fSetDefault = new StoredProc( dataSource , "defs" , "set_preference_default" );
this.fSetDefault.addParameter( "admin_id" , Types.INTEGER );
this.fSetDefault.addParameter( "pref_name" , Types.VARCHAR );
this.fSetDefault.addParameter( "default_value" , Types.VARCHAR );
}
@Autowired( required = true )
public void setTypesRegistry( PreferenceTypesRegistry registry )
{
this.registry = registry;
}
@Autowired( required = true )
public void setTransactionManager( PlatformTransactionManager transactionManager )
{
this.tTemplate = new TransactionTemplate( transactionManager );
}
@Autowired( required = true )
public void setLogger( Logger logger )
{
this.logger = logger.getSystemLogger( "PreferenceDefinitions" );
}
@Autowired( required = true )
public void setTranslator( Translator translator )
{
this.translator = translator;
}
@Override
public void registerGroup( final String name , final String displayName )
throws PreferenceDefinitionException
{
boolean success = this.tTemplate.execute( new TransactionCallback< Boolean >( ) {
@Override
public Boolean doInTransaction( TransactionStatus status )
{
return (Boolean) uocGroup.execute( name , displayName ).get( "success" );
}
} );
if ( !success ) {
throw new PreferenceDefinitionException( PreferenceDefinitionException.Error.MISSING_STRING );
}
this.logger.log( LogLevel.DEBUG , "registered preference group '" + name + "'" );
}
@Override
public void registerPreference( final String name , final String group , final String displayName ,
final String displayDescription , final Object defaultValue )
throws PreferenceDefinitionException
{
final Class< ? > type = defaultValue.getClass( );
final PreferenceType< ? > pType = this.registry.getType( type );
int errCode = this.tTemplate.execute( new TransactionCallback< Integer >( ) {
@Override
public Integer doInTransaction( TransactionStatus status )
{
return (Integer) uocDef.execute( group , name , displayName , displayDescription ,
type.getSimpleName( ) , pType.convert( defaultValue ) ).get( "err_code" );
}
} );
switch ( errCode ) {
case 0:
break;
case 1:
throw new PreferenceDefinitionException( PreferenceDefinitionException.Error.MISSING_GROUP );
case 2:
throw new PreferenceDefinitionException( PreferenceDefinitionException.Error.MISSING_STRING );
case 3:
throw new PreferenceDefinitionException( PreferenceDefinitionException.Error.INVALID_TYPE );
default:
throw new RuntimeException( "unknown error code " + errCode );
}
this.logger.log( LogLevel.DEBUG , "registered preference '" + name + "' in group '" + group + "'" );
}
private String translate( String strName )
{
try {
return this.translator.translate( "en" , strName );
} catch ( TranslationException e ) {
throw new RuntimeException( e );
}
}
@Override
@Transactional
public List< PrefCategory > getDefaults( )
{
List< PrefCategory > categories = new LinkedList< PrefCategory >( );
PrefCategory currentCategory = null;
String catName = "";
for ( PrefDefRecord def : this.dTemplate.query( "SELECT * FROM defs.preferences_view" , this.mPrefDef ) ) {
// Make sure we're modifying the right category
if ( currentCategory == null || !def.groupName.equals( catName ) ) {
currentCategory = new PrefCategory( );
catName = def.groupName;
currentCategory.setName( this.translate( def.groupDisplay ) );
categories.add( currentCategory );
}
// Add value
PrefValue value = new PrefValue( );
value.setId( def.name );
value.setName( this.translate( def.dName ) );
value.setDescription( this.translate( def.dDescription ) );
value.setValue( def.value );
PreferenceType< ? > dType = this.registry.getType( def.type );
if ( dType.getType( ) == String.class ) {
value.setType( PrefType.STRING );
} else if ( dType.getType( ) == Integer.class ) {
value.setType( PrefType.INTEGER );
} else if ( dType.getType( ) == Boolean.class ) {
value.setType( PrefType.BOOLEAN );
} else {
Map< String , String > choices = dType.getChoices( );
List< PrefChoice > cList = new LinkedList< PrefChoice >( );
for ( Map.Entry< String , String > entry : choices.entrySet( ) ) {
cList.add( new PrefChoice( entry.getKey( ) , this.translate( entry.getValue( ) ) ) );
}
value.setType( PrefType.CHOICE );
value.setChoices( cList );
}
currentCategory.addValue( value );
}
return categories;
}
@Override
@Transactional
public void setDefault( Administrator admin , String preference , String value )
{
String sql = "SELECT * FROM defs.preferences_view WHERE name = ?";
PrefDefRecord def;
try {
def = this.dTemplate.queryForObject( sql , this.mPrefDef , preference );
} catch ( EmptyResultDataAccessException e ) {
return;
}
PreferenceType< ? > pType = this.registry.getType( def.type );
Object inObject = pType.valueOf( value );
if ( inObject != null ) {
String dbValue = pType.convert( inObject );
this.fSetDefault.execute( admin.getId( ) , preference , dbValue );
}
}
}

View file

@ -0,0 +1,42 @@
package com.deepclone.lw.beans.prefs;
import java.util.Map;
import com.deepclone.lw.interfaces.prefs.PreferenceType;
abstract class PreferenceTypeImpl< T >
implements PreferenceType< T >
{
private final Class< T > type;
public PreferenceTypeImpl( Class< T > type )
{
this.type = type;
}
@Override
public Object valueOf( String inValue )
{
return this.valueOf( inValue , this.type );
}
@Override
public Map< String , String > getChoices( )
{
return null;
}
public Class< T > getType( )
{
return type;
}
}

View file

@ -0,0 +1,66 @@
package com.deepclone.lw.beans.prefs;
import java.util.HashMap;
import java.util.Map;
import com.deepclone.lw.interfaces.prefs.PreferenceType;
import com.deepclone.lw.interfaces.prefs.PreferenceTypesRegistry;
public class PreferenceTypesRegistryBean
implements PreferenceTypesRegistry
{
private final Map< String , PreferenceType< ? >> types = new HashMap< String , PreferenceType< ? > >( );
public PreferenceTypesRegistryBean( )
{
this.register( new StringPreferenceType( ) );
this.register( new IntPreferenceType( ) );
this.register( new BoolPreferenceType( ) );
}
void register( PreferenceType< ? > type )
{
String name = type.getType( ).getSimpleName( );
synchronized ( this.types ) {
if ( this.types.containsKey( name ) ) {
throw new IllegalArgumentException( "Type '" + name + "' already registered." );
}
this.types.put( name , type );
}
}
@Override
@SuppressWarnings( "unchecked" )
public < T > PreferenceType< T > getType( Class< T > jType )
{
PreferenceType< T > type;
synchronized ( this.types ) {
type = (PreferenceType< T >) this.types.get( jType.getSimpleName( ) );
}
if ( type == null ) {
throw new IllegalArgumentException( "Type '" + jType.getSimpleName( ) + "' is not registered." );
}
return type;
}
@Override
public PreferenceType< ? > getType( String typeName )
{
PreferenceType< ? > type;
synchronized ( this.types ) {
type = (PreferenceType< ? >) this.types.get( typeName );
}
if ( type == null ) {
throw new IllegalArgumentException( "Type '" + typeName + "' is not registered." );
}
return type;
}
}

View file

@ -0,0 +1,164 @@
package com.deepclone.lw.beans.prefs;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
import com.deepclone.lw.interfaces.prefs.AccountPreferences;
import com.deepclone.lw.interfaces.prefs.Preference;
import com.deepclone.lw.interfaces.prefs.PreferenceGroup;
import com.deepclone.lw.interfaces.prefs.PreferenceType;
import com.deepclone.lw.interfaces.prefs.PreferenceTypesRegistry;
import com.deepclone.lw.interfaces.prefs.PreferencesDAO;
import com.deepclone.lw.sqld.accounts.Account;
import com.deepclone.lw.utils.StoredProc;
public class PreferencesDAOBean
implements PreferencesDAO
{
private SimpleJdbcTemplate dTemplate;
private PreferenceTypesRegistry registry;
private StoredProc fReset;
private StoredProc fSetPref;
@Autowired( required = true )
public void setDataSource( DataSource dataSource )
{
this.dTemplate = new SimpleJdbcTemplate( dataSource );
this.fReset = new StoredProc( dataSource , "users" , "reset_preferences" );
this.fReset.addParameter( "a_id" , Types.INTEGER );
this.fSetPref = new StoredProc( dataSource , "users" , "set_preference" );
this.fSetPref.addParameter( "a_id" , Types.INTEGER );
this.fSetPref.addParameter( "p_name" , Types.VARCHAR );
this.fSetPref.addParameter( "p_value" , Types.VARCHAR );
}
@Autowired( required = true )
public void setTypesRegistry( PreferenceTypesRegistry registry )
{
this.registry = registry;
}
@Override
public AccountPreferences getPreferences( int accountId )
{
String sql = "SELECT * FROM users.preferences_view WHERE account_id = ?";
RowMapper< Map< String , String > > mapper = new RowMapper< Map< String , String > >( ) {
@Override
public Map< String , String > mapRow( ResultSet rs , int rowNum )
throws SQLException
{
final String[] names = {
"group_name" , "group_i18n_name" , "pref_name" , "pref_i18n_name" , "pref_i18n_description" ,
"pref_type" , "value"
};
Map< String , String > data = new HashMap< String , String >( );
for ( String n : names ) {
data.put( n , rs.getString( n ) );
}
return data;
}
};
List< PreferenceGroup > groups = new LinkedList< PreferenceGroup >( );
Map< String , String > prefGroups = new HashMap< String , String >( );
String last = null;
PreferenceGroup lg = null;
for ( Map< String , String > data : this.dTemplate.query( sql , mapper , accountId ) ) {
String gName = data.get( "group_name" );
if ( last == null || !last.equals( gName ) ) {
lg = new PreferenceGroup( gName , data.get( "group_i18n_name" ) );
groups.add( lg );
last = gName;
}
String pName = data.get( "pref_name" );
prefGroups.put( pName , gName );
PreferenceType< ? > prefType = this.registry.getType( data.get( "pref_type" ) );
new Preference( pName , lg , data.get( "pref_i18n_name" ) , data.get( "pref_i18n_description" ) , prefType ,
data.get( "value" ) );
}
return new AccountPreferences( groups , prefGroups );
}
@Override
public AccountPreferences getPreferences( Account account )
{
return this.getPreferences( account.getId( ) );
}
@Override
public void setPreferences( Account account , Map< String , String > values )
{
String sql = "SELECT pref_name , pref_type FROM users.preferences_view WHERE account_id = ?";
RowMapper< Map< String , String > > mapper = new RowMapper< Map< String , String > >( ) {
@Override
public Map< String , String > mapRow( ResultSet rs , int rowNum )
throws SQLException
{
final String[] names = {
"pref_name" , "pref_type"
};
Map< String , String > data = new HashMap< String , String >( );
for ( String n : names ) {
data.put( n , rs.getString( n ) );
}
return data;
}
};
for ( Map< String , String > def : this.dTemplate.query( sql , mapper , account.getId( ) ) ) {
String pName = def.get( "pref_name" );
PreferenceType< ? > pType = this.registry.getType( def.get( "pref_type" ) );
String inValue = values.get( pName );
if ( inValue == null ) {
continue;
}
Object inObject = pType.valueOf( inValue );
if ( inObject == null ) {
continue;
}
String dbValue = pType.convert( inObject );
this.fSetPref.execute( account.getId( ) , pName , dbValue );
}
}
@Override
public void resetPreferences( Account account )
{
this.fReset.execute( account.getId( ) );
}
}

View file

@ -0,0 +1,27 @@
package com.deepclone.lw.beans.prefs;
class StringPreferenceType
extends PreferenceTypeImpl< String >
{
public StringPreferenceType( )
{
super( String.class );
}
@Override
public String convert( Object value )
{
return ( value == null ) ? "" : (String) value;
}
@Override
public String valueOf( String dbValue , Class< String > type )
{
return dbValue;
}
}

View file

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<import resource="accounts/account-cleanup-bean.xml" />
<import resource="accounts/account-management-bean.xml" />
<import resource="accounts/admin-dao-bean.xml" />
<import resource="accounts/admin-recap-bean.xml" />
<import resource="accounts/administration-bean.xml" />
<import resource="accounts/bans-dao-bean.xml" />
<import resource="accounts/bans-processor-bean.xml" />
<import resource="accounts/default-preferences-bean.xml" />
<import resource="accounts/ip-ban-bean.xml" />
<import resource="accounts/preference-definitions-bean.xml" />
<import resource="accounts/preferences-dao-bean.xml" />
<import resource="accounts/quit-processor-bean.xml" />
<import resource="accounts/requests-expiration-bean.xml" />
<import resource="accounts/user-session-dao-bean.xml" />
<import resource="accounts/users-dao-bean.xml" />
<import resource="accounts/vacation-processor-bean.xml" />
</beans>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="accountCleanup" class="com.deepclone.lw.beans.acm.AccountCleanupBean" />
</beans>

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="accountManagement" class="com.deepclone.lw.beans.acm.AccountManagementBean" />
</beans>

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="adminDao" class="com.deepclone.lw.beans.admin.AdminDAOBean" />
</beans>

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="adminRecap" class="com.deepclone.lw.beans.admin.AdminRecapBean" />
</beans>

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="administration" class="com.deepclone.lw.beans.admin.AdministrationBean" />
</beans>

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="bansDao" class="com.deepclone.lw.beans.admin.BansDAOBean" />
</beans>

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="bansProcessor" class="com.deepclone.lw.beans.admin.BansProcessorBean" />
</beans>

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="defaultPreferences" class="com.deepclone.lw.beans.prefs.DefaultPreferencesBean" />
</beans>

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="ipBan" class="com.deepclone.lw.beans.admin.IpBanBean" />
</beans>

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="preferenceDefinitions" class="com.deepclone.lw.beans.prefs.PreferenceDefinitionsBean" />
<bean id="preferenceTypesRegistry" class="com.deepclone.lw.beans.prefs.PreferenceTypesRegistryBean" />
</beans>

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="preferencesDAO" class="com.deepclone.lw.beans.prefs.PreferencesDAOBean" />
</beans>

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="quitProcessor" class="com.deepclone.lw.beans.acm.QuitProcessorBean" />
</beans>

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="requestsExpiration" class="com.deepclone.lw.beans.acm.RequestsExpirationBean" />
</beans>

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="userSessionDao" class="com.deepclone.lw.beans.acm.UserSessionDAOBean" />
</beans>

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="usersDAO" class="com.deepclone.lw.beans.acm.UsersDAOBean" />
</beans>

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="vacationProcessor" class="com.deepclone.lw.beans.acm.VacationProcessorBean" />
</beans>

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java"/>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View file

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>legacyworlds-server-beans-bt</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.maven.ide.eclipse.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.maven.ide.eclipse.maven2Nature</nature>
</natures>
</projectDescription>

View file

@ -0,0 +1,6 @@
#Tue Apr 13 08:30:06 CEST 2010
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=1.6

View file

@ -0,0 +1,9 @@
#Tue Apr 13 08:30:04 CEST 2010
activeProfiles=
eclipse.preferences.version=1
fullBuildGoals=process-test-resources
includeModules=false
resolveWorkspaceProjects=true
resourceFilterGoals=process-resources resources\:testResources
skipCompilerPlugin=true
version=1

View file

@ -0,0 +1,25 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>legacyworlds-server-beans</artifactId>
<groupId>com.deepclone.lw</groupId>
<version>5.99.1</version>
</parent>
<dependencies>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>${com.thoughtworks.xstream.version}</version>
<type>jar</type>
</dependency>
</dependencies>
<groupId>com.deepclone.lw</groupId>
<artifactId>legacyworlds-server-beans-bt</artifactId>
<version>5.99.1</version>
<name>Legacy Worlds bug tracking system</name>
</project>

View file

@ -0,0 +1,179 @@
package com.deepclone.lw.beans.bt;
import java.util.Iterator;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import com.deepclone.lw.cmd.admin.adata.Administrator;
import com.deepclone.lw.cmd.admin.bt.BugsSummaryResponse;
import com.deepclone.lw.cmd.admin.bt.GetSnapshotResponse;
import com.deepclone.lw.cmd.admin.bt.ListBugsResponse;
import com.deepclone.lw.cmd.admin.bt.MergeError;
import com.deepclone.lw.cmd.admin.bt.MergeReportsResponse;
import com.deepclone.lw.cmd.admin.bt.PostCommentResponse;
import com.deepclone.lw.cmd.admin.bt.ReportBugResponse;
import com.deepclone.lw.cmd.admin.bt.ViewBugResponse;
import com.deepclone.lw.cmd.bt.data.BugEvent;
import com.deepclone.lw.cmd.bt.data.BugEventType;
import com.deepclone.lw.cmd.bt.data.BugReport;
import com.deepclone.lw.cmd.bt.data.BugStatus;
import com.deepclone.lw.interfaces.bt.AdminBugs;
import com.deepclone.lw.interfaces.bt.BugsDAO;
@Transactional
public class AdminBugsBean
implements AdminBugs
{
private BugsDAO bugsDao;
@Autowired( required = true )
public void setBugsDao( BugsDAO bugsDao )
{
this.bugsDao = bugsDao;
}
private List< BugEvent > getBugEvents( long bugId )
{
List< BugEvent > events = this.bugsDao.getEvents( bugId );
Iterator< BugEvent > it = events.iterator( );
BugStatus status = BugStatus.PENDING;
boolean pub = false;
while ( it.hasNext( ) ) {
BugEvent event = it.next( );
if ( event.getType( ) == BugEventType.STATUS ) {
if ( event.getStatus( ) == status ) {
it.remove( );
} else {
status = event.getStatus( );
}
} else if ( event.getType( ) == BugEventType.VISIBILITY ) {
if ( event.getVisible( ) == pub ) {
it.remove( );
} else {
pub = event.getVisible( );
}
}
}
return events;
}
@Override
public BugsSummaryResponse getSummary( Administrator admin )
{
long pending = this.bugsDao.countReports( admin , BugStatus.PENDING , false );
long open = this.bugsDao.countReports( admin , BugStatus.OPEN , false );
long own = this.bugsDao.countReports( admin , null , true );
long updated = this.bugsDao.countUpdatedReports( admin );
long total = this.bugsDao.countReports( admin , null , false );
return new BugsSummaryResponse( admin , pending , open , own , updated , total );
}
@Override
public ListBugsResponse getBugs( Administrator admin , BugStatus status , boolean ownOnly , long first , int count )
{
long nBugs = this.bugsDao.countReports( admin , status , ownOnly );
List< BugReport > bugs = this.bugsDao.getReports( admin , status , ownOnly , first , count );
return new ListBugsResponse( admin , status , ownOnly , first , count , nBugs , bugs );
}
@Override
public ReportBugResponse postReport( Administrator admin , String title , String contents , boolean publicReport )
{
long bugId = this.bugsDao.postReport( admin , title , contents , publicReport );
return new ReportBugResponse( admin , bugId );
}
@Override
public ViewBugResponse getReport( Administrator admin , long bugId )
{
BugReport report = this.bugsDao.getReport( admin , bugId );
if ( report == null ) {
return new ViewBugResponse( admin , false );
}
return new ViewBugResponse( admin , report , this.getBugEvents( bugId ) );
}
@Override
public PostCommentResponse postComment( Administrator admin , long bugId , String comment , boolean publicComment )
{
this.bugsDao.postComment( admin , bugId , comment , publicComment );
return new PostCommentResponse( admin );
}
@Override
public void moderateComment( Administrator admin , long commentId , boolean validation )
{
if ( validation ) {
this.bugsDao.showComment( admin , commentId );
} else {
this.bugsDao.deleteComment( admin , commentId );
}
}
@Override
public void validateReport( Administrator admin , long bugId , BugStatus status , boolean publicReport ,
int credits , boolean snapshot )
{
this.bugsDao.validateReport( admin , bugId , status , publicReport , credits , snapshot );
}
@Override
public void setStatus( Administrator admin , long bugId , BugStatus status )
{
this.bugsDao.setStatus( admin , bugId , status );
}
@Override
public void toggleVisibility( Administrator admin , long bugId )
{
this.bugsDao.toggleVisibility( admin , bugId );
}
@Override
public MergeReportsResponse mergeReports( Administrator admin , long id , long mergeId )
{
int errCode = this.bugsDao.mergeReports( admin , id , mergeId );
if ( errCode == 0 ) {
return new MergeReportsResponse( admin );
}
BugReport report = this.bugsDao.getReport( admin , id );
if ( report == null ) {
return new MergeReportsResponse( admin , false );
}
return new MergeReportsResponse( admin , report , this.getBugEvents( id ) ,
MergeError.values( )[ errCode - 1 ] , mergeId );
}
@Override
public GetSnapshotResponse getSnapshot( Administrator admin , long bugId )
{
String snapshot = this.bugsDao.getSnapshot( bugId );
if ( snapshot == null ) {
return new GetSnapshotResponse( admin , false );
}
return new GetSnapshotResponse( admin , snapshot );
}
}

View file

@ -0,0 +1,395 @@
package com.deepclone.lw.beans.bt;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.List;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
import com.deepclone.lw.cmd.admin.adata.Administrator;
import com.deepclone.lw.cmd.bt.data.*;
import com.deepclone.lw.interfaces.bt.BugsDAO;
import com.deepclone.lw.utils.StoredProc;
public class BugsDAOBean
implements BugsDAO
{
private SimpleJdbcTemplate dTemplate;
private final RowMapper< BugReport > mBugReport;
private final RowMapper< BugEvent > mBugEvent;
private final RowMapper< String > mString;
private StoredProc fPostUserReport;
private StoredProc fPostAdminReport;
private StoredProc fPostUserComment;
private StoredProc fPostAdminComment;
private StoredProc fShowComment;
private StoredProc fDeleteComment;
private StoredProc fValidateReport;
private StoredProc fSetStatus;
private StoredProc fToggleVisibility;
private StoredProc fMerge;
public BugsDAOBean( )
{
this.mBugReport = new RowMapper< BugReport >( ) {
@Override
public BugReport mapRow( ResultSet rs , int rowNum )
throws SQLException
{
BugSubmitter sub;
BugReport br = new BugReport( );
br.setReportId( rs.getLong( "bug_report_id" ) );
br.setTitle( rs.getString( "title" ) );
br.setPosted( rs.getTimestamp( "posted" ) );
br.setVisible( rs.getBoolean( "visible" ) );
br.setStatus( BugStatus.valueOf( rs.getString( "status" ) ) );
br.setLastUpdate( rs.getTimestamp( "last_update" ) );
br.setUpdated( rs.getBoolean( "updated" ) );
sub = new BugSubmitter( );
sub.setAdmin( rs.getBoolean( "initial_submitter_admin" ) );
sub.setName( rs.getString( "initial_submitter_name" ) );
sub.setUserId( (Integer) rs.getObject( "initial_submitter_uid" ) );
br.setInitialSubmitter( sub );
sub = new BugSubmitter( );
sub.setAdmin( rs.getBoolean( "last_submitter_admin" ) );
sub.setName( rs.getString( "last_submitter_name" ) );
sub.setUserId( (Integer) rs.getObject( "last_submitter_uid" ) );
br.setLatestSubmitter( sub );
return br;
}
};
this.mBugEvent = new RowMapper< BugEvent >( ) {
@Override
public BugEvent mapRow( ResultSet rs , int rowNum )
throws SQLException
{
BugSubmitter sub;
BugEvent be = new BugEvent( );
be.setId( rs.getLong( "event_id" ) );
be.setType( BugEventType.valueOf( rs.getString( "event_type" ) ) );
be.setTimestamp( rs.getTimestamp( "event_timestamp" ) );
be.setTitle( rs.getString( "title" ) );
be.setContents( rs.getString( "contents" ) );
BugEventType type = be.getType( );
switch ( type ) {
case STATUS:
be.setStatus( BugStatus.valueOf( rs.getString( "status" ) ) );
break;
case COMMENT:
case VISIBILITY:
case INIT:
be.setVisible( rs.getBoolean( "visible" ) );
break;
case MERGE:
be.setMergedId( rs.getLong( "merged_report_id" ) );
break;
}
sub = new BugSubmitter( );
sub.setAdmin( rs.getBoolean( "submitter_admin" ) );
sub.setName( rs.getString( "submitter_name" ) );
sub.setUserId( (Integer) rs.getObject( "submitter_uid" ) );
be.setSubmitter( sub );
return be;
}
};
this.mString = new RowMapper< String >( ) {
@Override
public String mapRow( ResultSet rs , int rowNum )
throws SQLException
{
return rs.getString( 1 );
}
};
}
@Autowired( required = true )
public void setDataSource( DataSource dataSource )
{
this.dTemplate = new SimpleJdbcTemplate( dataSource );
this.fPostUserReport = new StoredProc( dataSource , "bugs" , "post_player_report" );
this.fPostUserReport.addParameter( "empire_id" , Types.INTEGER );
this.fPostUserReport.addParameter( "title" , Types.VARCHAR );
this.fPostUserReport.addParameter( "description" , Types.VARCHAR );
this.fPostUserReport.addParameter( "extra" , Types.VARCHAR );
this.fPostUserReport.addOutput( "report_id" , Types.BIGINT );
this.fPostUserReport.addOutput( "group_id" , Types.BIGINT );
this.fPostAdminReport = new StoredProc( dataSource , "bugs" , "post_admin_report" );
this.fPostAdminReport.addParameter( "admin_id" , Types.INTEGER );
this.fPostAdminReport.addParameter( "title" , Types.VARCHAR );
this.fPostAdminReport.addParameter( "description" , Types.VARCHAR );
this.fPostAdminReport.addParameter( "public_report" , Types.BOOLEAN );
this.fPostAdminReport.addOutput( "report_id" , Types.BIGINT );
this.fPostAdminReport.addOutput( "group_id" , Types.BIGINT );
this.fPostUserComment = new StoredProc( dataSource , "bugs" , "post_player_comment" );
this.fPostUserComment.addParameter( "empire_id" , Types.INTEGER );
this.fPostUserComment.addParameter( "report_id" , Types.BIGINT );
this.fPostUserComment.addParameter( "comment" , Types.VARCHAR );
this.fPostAdminComment = new StoredProc( dataSource , "bugs" , "post_admin_comment" );
this.fPostAdminComment.addParameter( "admin_id" , Types.INTEGER );
this.fPostAdminComment.addParameter( "report_id" , Types.BIGINT );
this.fPostAdminComment.addParameter( "comment" , Types.VARCHAR );
this.fPostAdminComment.addParameter( "public_comment" , Types.BOOLEAN );
this.fShowComment = new StoredProc( dataSource , "bugs" , "show_comment" );
this.fShowComment.addParameter( "admin_id" , Types.INTEGER );
this.fShowComment.addParameter( "comment_id" , Types.BIGINT );
this.fDeleteComment = new StoredProc( dataSource , "bugs" , "delete_comment" );
this.fDeleteComment.addParameter( "admin_id" , Types.INTEGER );
this.fDeleteComment.addParameter( "comment_id" , Types.BIGINT );
this.fValidateReport = new StoredProc( dataSource , "bugs" , "validate_report" );
this.fValidateReport.addParameter( "admin_id" , Types.INTEGER );
this.fValidateReport.addParameter( "report_id" , Types.BIGINT );
this.fValidateReport.addParameter( "new_status" , "bug_status_type" );
this.fValidateReport.addParameter( "public_report" , Types.BOOLEAN );
this.fValidateReport.addParameter( "grant_credits" , Types.INTEGER );
this.fValidateReport.addParameter( "keep_snapshot" , Types.BOOLEAN );
this.fSetStatus = new StoredProc( dataSource , "bugs" , "set_report_status" );
this.fSetStatus.addParameter( "admin_id" , Types.INTEGER );
this.fSetStatus.addParameter( "report_id" , Types.BIGINT );
this.fSetStatus.addParameter( "new_status" , "bug_status_type" );
this.fToggleVisibility = new StoredProc( dataSource , "bugs" , "toggle_report_visibility" );
this.fToggleVisibility.addParameter( "admin_id" , Types.INTEGER );
this.fToggleVisibility.addParameter( "report_id" , Types.BIGINT );
this.fMerge = new StoredProc( dataSource , "bugs" , "merge_reports" );
this.fMerge.addParameter( "admin_id" , Types.INTEGER );
this.fMerge.addParameter( "report1_id" , Types.BIGINT );
this.fMerge.addParameter( "report2_id" , Types.BIGINT );
this.fMerge.addOutput( "err_code" , Types.INTEGER );
}
@Override
public long countReports( int empireId , BugStatus status , boolean ownOnly )
{
StringBuilder builder = new StringBuilder( );
List< Object > qData = new ArrayList< Object >( );
qData.add( (Integer) empireId );
builder.append( "SELECT count(*) FROM bugs.br_user_view WHERE empire_id = ?" );
this.addQueryParameters( builder , qData , status , ownOnly );
Object[] args = qData.toArray( );
return this.dTemplate.queryForLong( builder.toString( ) , args );
}
@Override
public long countReports( Administrator admin , BugStatus status , boolean ownOnly )
{
StringBuilder builder = new StringBuilder( );
List< Object > qData = new ArrayList< Object >( );
qData.add( (Integer) admin.getId( ) );
builder.append( "SELECT count(*) FROM bugs.br_admin_view WHERE administrator_id = ?" );
this.addQueryParameters( builder , qData , status , ownOnly );
Object[] args = qData.toArray( );
return this.dTemplate.queryForLong( builder.toString( ) , args );
}
@Override
public long countUpdatedReports( Administrator admin )
{
String sql = "SELECT count(*) FROM bugs.br_admin_view WHERE administrator_id = ? AND updated";
return this.dTemplate.queryForLong( sql , admin.getId( ) );
}
@Override
public List< BugReport > getReports( int empireId , BugStatus status , boolean ownOnly , long first , int count )
{
StringBuilder builder = new StringBuilder( ).append( "SELECT * FROM bugs.br_user_view WHERE empire_id = ?" );
List< Object > qData = new ArrayList< Object >( );
qData.add( (Integer) empireId );
this.addQueryParameters( builder , qData , status , ownOnly );
this.addWindowParameters( builder , qData , first , count );
Object[] args = qData.toArray( );
return this.dTemplate.query( builder.toString( ) , this.mBugReport , args );
}
@Override
public List< BugReport > getReports( Administrator admin , BugStatus status , boolean ownOnly , long first ,
int count )
{
StringBuilder builder = new StringBuilder( );
List< Object > qData = new ArrayList< Object >( );
qData.add( (Integer) admin.getId( ) );
builder.append( "SELECT * FROM bugs.br_admin_view WHERE administrator_id = ?" );
this.addQueryParameters( builder , qData , status , ownOnly );
this.addWindowParameters( builder , qData , first , count );
Object[] args = qData.toArray( );
return this.dTemplate.query( builder.toString( ) , this.mBugReport , args );
}
private void addQueryParameters( StringBuilder builder , List< Object > qData , BugStatus status , boolean ownOnly )
{
if ( status != null ) {
builder.append( " AND status = ?" );
qData.add( status.toString( ) );
}
if ( ownOnly ) {
builder.append( " AND own_report" );
}
}
private void addWindowParameters( StringBuilder builder , List< Object > qData , long first , int count )
{
builder.append( " ORDER BY last_update DESC , bug_report_id DESC OFFSET ? LIMIT ?" );
qData.add( (Long) first );
qData.add( (Integer) count );
}
@Override
public BugReport getReport( int empireId , long reportId )
{
return this.getReport( "player" , empireId , reportId );
}
@Override
public BugReport getReport( Administrator admin , long reportId )
{
return this.getReport( "admin" , admin.getId( ) , reportId );
}
private BugReport getReport( String viewerType , int viewerId , long reportId )
{
String sql = "SELECT * FROM bugs.read_" + viewerType + "_report( ? , ? )";
try {
return this.dTemplate.queryForObject( sql , this.mBugReport , viewerId , reportId );
} catch ( EmptyResultDataAccessException e ) {
return null;
}
}
@Override
public long postReport( int empireId , String title , String contents , String extra )
{
return (Long) this.fPostUserReport.execute( empireId , title , contents , extra ).get( "report_id" );
}
@Override
public long postReport( Administrator admin , String title , String contents , boolean publicReport )
{
return (Long) this.fPostAdminReport.execute( admin.getId( ) , title , contents , publicReport ).get(
"report_id" );
}
@Override
public void postComment( int empireId , long reportId , String comment )
{
this.fPostUserComment.execute( empireId , reportId , comment );
}
@Override
public void postComment( Administrator admin , long reportId , String comment , boolean publicComment )
{
this.fPostAdminComment.execute( admin.getId( ) , reportId , comment , publicComment );
}
@Override
public List< BugEvent > getEvents( long bugId )
{
String sql = "SELECT * FROM bugs.br_events WHERE bug_report_id = ?";
return this.dTemplate.query( sql , this.mBugEvent , bugId );
}
@Override
public void showComment( Administrator admin , long commentId )
{
this.fShowComment.execute( admin.getId( ) , commentId );
}
@Override
public void deleteComment( Administrator admin , long commentId )
{
this.fDeleteComment.execute( admin.getId( ) , commentId );
}
@Override
public void validateReport( Administrator admin , long bugId , BugStatus status , boolean publicReport ,
int credits , boolean snapshot )
{
this.fValidateReport.execute( admin.getId( ) , bugId , status.toString( ) , publicReport , credits , snapshot );
}
@Override
public void setStatus( Administrator admin , long bugId , BugStatus status )
{
this.fSetStatus.execute( admin.getId( ) , bugId , status.toString( ) );
}
@Override
public void toggleVisibility( Administrator admin , long bugId )
{
this.fToggleVisibility.execute( admin.getId( ) , bugId );
}
@Override
public int mergeReports( Administrator admin , long id , long mergeId )
{
return (Integer) this.fMerge.execute( admin.getId( ) , id , mergeId ).get( "err_code" );
}
@Override
public String getSnapshot( long bugId )
{
String sql = "SELECT account_status FROM bugs.account_status_data WHERE event_id = ?";
return this.dTemplate.queryForObject( sql , this.mString , bugId );
}
}

View file

@ -0,0 +1,240 @@
package com.deepclone.lw.beans.bt;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
import com.deepclone.lw.beans.bt.esdata.*;
import com.deepclone.lw.interfaces.bt.EmpireSummary;
import com.thoughtworks.xstream.XStream;
public class EmpireSummaryBean
implements EmpireSummary
{
private SimpleJdbcTemplate dTemplate;
private final XStream xStream;
private final RowMapper< DebugInformation > mMainInfo;
private final RowMapper< ResearchInformation > mResearch;
private final RowMapper< PlanetInformation > mPlanet;
private final RowMapper< QueueItemInformation > mQueueItem;
private final RowMapper< BuildingsInformation > mBuildings;
private final RowMapper< FleetInformation > mFleet;
private final RowMapper< ShipsInformation > mShips;
public EmpireSummaryBean( )
{
this.xStream = new XStream( );
this.xStream.processAnnotations( new Class< ? >[] {
AccountInformation.class , AllianceInformation.class , BuildingsInformation.class ,
DebugInformation.class , EmpireInformation.class , FleetInformation.class , MovementInformation.class ,
PlanetInformation.class , QueueInformation.class , QueueItemInformation.class ,
ResearchInformation.class , ShipsInformation.class , SystemInformation.class
} );
this.mMainInfo = new RowMapper< DebugInformation >( ) {
@Override
public DebugInformation mapRow( ResultSet rs , int rowNum )
throws SQLException
{
DebugInformation di = new DebugInformation( );
di.getSystem( ).setNextTick( rs.getLong( "next_tick" ) );
di.getSystem( ).setCurrentTick( (Long) rs.getObject( "current_tick" ) );
di.getAccount( ).setId( rs.getInt( "account_id" ) );
di.getAccount( ).setAddress( rs.getString( "account_address" ) );
di.getAccount( ).setGameCredits( rs.getInt( "game_credits" ) );
di.getAccount( ).setStatus( rs.getString( "account_status" ) );
di.getAccount( ).setLanguage( rs.getString( "account_language" ) );
di.getEmpire( ).setId( rs.getInt( "empire_id" ) );
di.getEmpire( ).setName( rs.getString( "empire_name" ) );
di.getEmpire( ).setCash( rs.getDouble( "cash" ) );
String allianceTag = rs.getString( "alliance_tag" );
if ( allianceTag != null ) {
AllianceInformation alliance = new AllianceInformation( );
alliance.setId( rs.getInt( "alliance_id" ) );
alliance.setTag( allianceTag );
alliance.setPending( rs.getBoolean( "alliance_pending" ) );
di.getEmpire( ).setAlliance( alliance );
}
return di;
}
};
this.mResearch = new RowMapper< ResearchInformation >( ) {
@Override
public ResearchInformation mapRow( ResultSet rs , int rowNum )
throws SQLException
{
ResearchInformation ri = new ResearchInformation( );
ri.setId( rs.getInt( "line_id" ) );
ri.setCurrentLevel( rs.getInt( "level" ) );
ri.setLevelName( rs.getString( "name" ) );
ri.setAccumulated( rs.getDouble( "accumulated" ) );
return ri;
}
};
this.mPlanet = new RowMapper< PlanetInformation >( ) {
@Override
public PlanetInformation mapRow( ResultSet rs , int rowNum )
throws SQLException
{
PlanetInformation pi = new PlanetInformation( );
pi.setId( rs.getInt( "planet_id" ) );
pi.setPopulation( rs.getDouble( "population" ) );
pi.setCurrentHappiness( rs.getDouble( "current_happiness" ) );
pi.setTargetHappiness( rs.getDouble( "target_happiness" ) );
pi.getCivilianQueue( ).setAccMoney( rs.getDouble( "civ_money" ) );
pi.getCivilianQueue( ).setAccWork( rs.getDouble( "civ_work" ) );
pi.getMilitaryQueue( ).setAccMoney( rs.getDouble( "mil_money" ) );
pi.getMilitaryQueue( ).setAccWork( rs.getDouble( "mil_work" ) );
return pi;
}
};
this.mQueueItem = new RowMapper< QueueItemInformation >( ) {
@Override
public QueueItemInformation mapRow( ResultSet rs , int rowNum )
throws SQLException
{
QueueItemInformation qii = new QueueItemInformation( );
qii.setPlanetId( rs.getInt( "planet_id" ) );
qii.setMilitary( rs.getBoolean( "military" ) );
qii.setId( rs.getInt( "item_id" ) );
qii.setName( rs.getString( "item_name" ) );
qii.setDestroy( rs.getBoolean( "destroy" ) );
qii.setAmount( rs.getInt( "amount" ) );
return qii;
}
};
this.mBuildings = new RowMapper< BuildingsInformation >( ) {
@Override
public BuildingsInformation mapRow( ResultSet rs , int rowNum )
throws SQLException
{
BuildingsInformation bi = new BuildingsInformation( );
bi.setPlanetId( rs.getInt( "planet_id" ) );
bi.setId( rs.getInt( "building_id" ) );
bi.setName( rs.getString( "building_name" ) );
bi.setAmount( rs.getInt( "amount" ) );
bi.setDamage( rs.getDouble( "damage" ) );
return bi;
}
};
this.mFleet = new RowMapper< FleetInformation >( ) {
@Override
public FleetInformation mapRow( ResultSet rs , int rowNum )
throws SQLException
{
FleetInformation fi = new FleetInformation( );
fi.setId( rs.getLong( "fleet_id" ) );
fi.setName( rs.getString( "fleet_name" ) );
fi.setStatus( rs.getString( "status" ) );
fi.setAttacking( rs.getBoolean( "attacking" ) );
fi.setLocationId( rs.getInt( "location_id" ) );
fi.setLocationName( rs.getString( "location_name" ) );
Integer sourceId = (Integer) rs.getObject( "source_id" );
if ( sourceId != null ) {
MovementInformation mi = new MovementInformation( );
mi.setSourceId( sourceId );
mi.setSourceName( rs.getString( "source_name" ) );
mi.setTimeLeft( rs.getInt( "time_left" ) );
mi.setStateTimeLeft( rs.getInt( "state_time_left" ) );
mi.setNearId( (Integer) rs.getObject( "ref_point_id" ) );
mi.setNearName( rs.getString( "ref_point_name" ) );
mi.setOutwards( (Boolean) rs.getObject( "outwards" ) );
mi.setPastRefPoint( (Boolean) rs.getObject( "past_ref_point" ) );
mi.setStartX( (Float) rs.getObject( "start_x" ) );
mi.setStartY( (Float) rs.getObject( "start_y" ) );
fi.setMovement( mi );
}
return fi;
}
};
this.mShips = new RowMapper< ShipsInformation >( ) {
@Override
public ShipsInformation mapRow( ResultSet rs , int rowNum )
throws SQLException
{
ShipsInformation si = new ShipsInformation( );
si.setFleetId( rs.getLong( "fleet_id" ) );
si.setId( rs.getInt( "ship_id" ) );
si.setName( rs.getString( "ship_name" ) );
si.setAmount( rs.getInt( "amount" ) );
si.setDamage( rs.getDouble( "damage" ) );
return si;
}
};
}
@Autowired( required = true )
public void setDataSource( DataSource dataSource )
{
this.dTemplate = new SimpleJdbcTemplate( dataSource );
}
@Override
public String getSummary( int empireId )
{
String sql = "SELECT * FROM bugs.dump_main_view WHERE empire_id = ?";
DebugInformation di = this.dTemplate.queryForObject( sql , this.mMainInfo , empireId );
sql = "SELECT * FROM bugs.dump_research_view WHERE empire_id = ?";
for ( ResearchInformation ri : this.dTemplate.query( sql , this.mResearch , empireId ) ) {
di.getResearch( ).add( ri );
}
sql = "SELECT * FROM bugs.dump_planets_view WHERE empire_id = ?";
Map< Integer , PlanetInformation > planets = new HashMap< Integer , PlanetInformation >( );
for ( PlanetInformation pi : this.dTemplate.query( sql , this.mPlanet , empireId ) ) {
di.getPlanets( ).add( pi );
planets.put( pi.getId( ) , pi );
}
sql = "SELECT * FROM bugs.dump_queues_view WHERE empire_id = ? ORDER BY queue_order";
for ( QueueItemInformation qii : this.dTemplate.query( sql , this.mQueueItem , empireId ) ) {
PlanetInformation pi = planets.get( qii.getPlanetId( ) );
QueueInformation qi = ( qii.isMilitary( ) ? pi.getMilitaryQueue( ) : pi.getCivilianQueue( ) );
qi.getItems( ).add( qii );
}
sql = "SELECT * FROM bugs.dump_buildings_view WHERE empire_id = ?";
for ( BuildingsInformation bi : this.dTemplate.query( sql , this.mBuildings , empireId ) ) {
planets.get( bi.getPlanetId( ) ).getBuildings( ).add( bi );
}
sql = "SELECT * FROM bugs.dump_fleets_view WHERE empire_id = ?";
Map< Long , FleetInformation > fleets = new HashMap< Long , FleetInformation >( );
for ( FleetInformation fi : this.dTemplate.query( sql , this.mFleet , empireId ) ) {
di.getFleets( ).add( fi );
fleets.put( fi.getId( ) , fi );
}
sql = "SELECT * FROM bugs.dump_ships_view WHERE empire_id = ?";
for ( ShipsInformation si : this.dTemplate.query( sql , this.mShips , empireId ) ) {
fleets.get( si.getFleetId( ) ).getShips( ).add( si );
}
return this.xStream.toXML( di );
}
}

View file

@ -0,0 +1,114 @@
package com.deepclone.lw.beans.bt;
import java.util.Iterator;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import com.deepclone.lw.cmd.bt.data.*;
import com.deepclone.lw.cmd.player.bt.*;
import com.deepclone.lw.cmd.player.gdata.GamePageData;
import com.deepclone.lw.interfaces.bt.*;
import com.deepclone.lw.interfaces.game.EmpireManagement;
@Transactional
public class PlayerBugsBean
implements PlayerBugs
{
private EmpireManagement empireMgr;
private BugsDAO bugsDao;
private EmpireSummary summary;
@Autowired( required = true )
public void setBugsDao( BugsDAO bugsDao )
{
this.bugsDao = bugsDao;
}
@Autowired( required = true )
public void setEmpireMgr( EmpireManagement empireMgr )
{
this.empireMgr = empireMgr;
}
@Autowired( required = true )
public void setSummary( EmpireSummary summary )
{
this.summary = summary;
}
@Override
public ListBugsResponse getBugs( int empireId , BugStatus status , boolean ownOnly , long first , int count )
{
long nBugs = this.bugsDao.countReports( empireId , status , ownOnly );
List< BugReport > bugs = this.bugsDao.getReports( empireId , status , ownOnly , first , count );
GamePageData page = this.empireMgr.getGeneralInformation( empireId );
return new ListBugsResponse( page , status , ownOnly , first , count , nBugs , bugs );
}
@Override
public ReportBugResponse postReport( int empireId , String title , String desc )
{
long bugId = this.bugsDao.postReport( empireId , title , desc , this.summary.getSummary( empireId ) );
return new ReportBugResponse( this.empireMgr.getGeneralInformation( empireId ) , bugId );
}
@Override
public ViewBugResponse getReport( int empireId , long bugId )
{
GamePageData page = this.empireMgr.getGeneralInformation( empireId );
BugReport report = this.bugsDao.getReport( empireId , bugId );
if ( report == null ) {
return new ViewBugResponse( page );
}
List< BugEvent > events = this.bugsDao.getEvents( bugId );
Iterator< BugEvent > it = events.iterator( );
BugStatus status = BugStatus.PENDING;
boolean pub = false;
while ( it.hasNext( ) ) {
BugEvent event = it.next( );
BugEventType type = event.getType( );
if ( type == BugEventType.STATUS ) {
if ( event.getStatus( ) == status ) {
it.remove( );
} else {
status = event.getStatus( );
}
} else if ( type == BugEventType.VISIBILITY ) {
if ( event.getVisible( ) == pub ) {
it.remove( );
} else {
pub = event.getVisible( );
}
} else if ( type == BugEventType.COMMENT && !event.getVisible( ) ) {
BugSubmitter submitter = event.getSubmitter( );
if ( submitter.isAdmin( ) || submitter.getUserId( ) == null
|| !page.getEmpire( ).equals( submitter.getName( ) ) ) {
it.remove( );
}
}
}
return new ViewBugResponse( page , report , events );
}
@Override
public PostCommentResponse postComment( int empireId , long reportId , String comment )
{
this.bugsDao.postComment( empireId , reportId , comment );
return new PostCommentResponse( this.empireMgr.getGeneralInformation( empireId ) , true );
}
}

View file

@ -0,0 +1,98 @@
package com.deepclone.lw.beans.bt.esdata;
import java.io.Serializable;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
@XStreamAlias( "account" )
public class AccountInformation
implements Serializable
{
private static final long serialVersionUID = 1L;
@XStreamAsAttribute
@XStreamAlias( "id" )
private int id;
@XStreamAsAttribute
@XStreamAlias( "address" )
private String address;
@XStreamAsAttribute
@XStreamAlias( "language" )
private String language;
@XStreamAsAttribute
@XStreamAlias( "game-credits" )
private int gameCredits;
@XStreamAsAttribute
@XStreamAlias( "status" )
private String status;
public int getId( )
{
return id;
}
public void setId( int id )
{
this.id = id;
}
public String getAddress( )
{
return address;
}
public void setAddress( String address )
{
this.address = address;
}
public String getLanguage( )
{
return language;
}
public void setLanguage( String language )
{
this.language = language;
}
public int getGameCredits( )
{
return gameCredits;
}
public void setGameCredits( int gameCredits )
{
this.gameCredits = gameCredits;
}
public String getStatus( )
{
return status;
}
public void setStatus( String status )
{
this.status = status;
}
}

View file

@ -0,0 +1,66 @@
package com.deepclone.lw.beans.bt.esdata;
import java.io.Serializable;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
@XStreamAlias( "alliance" )
public class AllianceInformation
implements Serializable
{
private static final long serialVersionUID = 1L;
@XStreamAsAttribute
@XStreamAlias( "id" )
private int id;
@XStreamAsAttribute
@XStreamAlias( "tag" )
private String tag;
@XStreamAsAttribute
@XStreamAlias( "pending" )
private boolean pending;
public int getId( )
{
return id;
}
public void setId( int id )
{
this.id = id;
}
public String getTag( )
{
return tag;
}
public void setTag( String tag )
{
this.tag = tag;
}
public boolean isPending( )
{
return pending;
}
public void setPending( boolean pending )
{
this.pending = pending;
}
}

View file

@ -0,0 +1,96 @@
package com.deepclone.lw.beans.bt.esdata;
import java.io.Serializable;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
@XStreamAlias( "building" )
public class BuildingsInformation
implements Serializable
{
private static final long serialVersionUID = 1L;
private transient int planetId;
@XStreamAsAttribute
@XStreamAlias( "id" )
private int id;
@XStreamAsAttribute
@XStreamAlias( "name" )
private String name;
@XStreamAsAttribute
@XStreamAlias( "amount" )
private int amount;
@XStreamAsAttribute
@XStreamAlias( "damage" )
private double damage;
public int getPlanetId( )
{
return planetId;
}
public void setPlanetId( int planetId )
{
this.planetId = planetId;
}
public int getId( )
{
return id;
}
public void setId( int id )
{
this.id = id;
}
public String getName( )
{
return name;
}
public void setName( String name )
{
this.name = name;
}
public int getAmount( )
{
return amount;
}
public void setAmount( int amount )
{
this.amount = amount;
}
public double getDamage( )
{
return damage;
}
public void setDamage( double damage )
{
this.damage = damage;
}
}

View file

@ -0,0 +1,81 @@
package com.deepclone.lw.beans.bt.esdata;
import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
@XStreamAlias( "debug" )
public class DebugInformation
implements Serializable
{
private static final long serialVersionUID = 1L;
@XStreamAsAttribute
@XStreamAlias( "dump-version" )
private int version = 1;
private SystemInformation system = new SystemInformation( );
private AccountInformation account = new AccountInformation( );
private EmpireInformation empire = new EmpireInformation( );
@XStreamAlias( "research" )
private List< ResearchInformation > research = new LinkedList< ResearchInformation >( );
@XStreamAlias( "planets" )
private List< PlanetInformation > planets = new LinkedList< PlanetInformation >( );
@XStreamAlias( "fleets" )
private List< FleetInformation > fleets = new LinkedList< FleetInformation >( );
public int getVersion( )
{
return version;
}
public SystemInformation getSystem( )
{
return system;
}
public AccountInformation getAccount( )
{
return account;
}
public EmpireInformation getEmpire( )
{
return empire;
}
public List< ResearchInformation > getResearch( )
{
return research;
}
public List< PlanetInformation > getPlanets( )
{
return planets;
}
public List< FleetInformation > getFleets( )
{
return fleets;
}
}

View file

@ -0,0 +1,80 @@
package com.deepclone.lw.beans.bt.esdata;
import java.io.Serializable;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
@XStreamAlias( "empire" )
public class EmpireInformation
implements Serializable
{
private static final long serialVersionUID = 1L;
@XStreamAsAttribute
@XStreamAlias( "id" )
private int id;
@XStreamAsAttribute
@XStreamAlias( "name" )
private String name;
@XStreamAsAttribute
@XStreamAlias( "cash" )
private double cash;
private AllianceInformation alliance;
public int getId( )
{
return id;
}
public void setId( int id )
{
this.id = id;
}
public String getName( )
{
return name;
}
public void setName( String name )
{
this.name = name;
}
public double getCash( )
{
return cash;
}
public void setCash( double cash )
{
this.cash = cash;
}
public AllianceInformation getAlliance( )
{
return alliance;
}
public void setAlliance( AllianceInformation alliance )
{
this.alliance = alliance;
}
}

View file

@ -0,0 +1,133 @@
package com.deepclone.lw.beans.bt.esdata;
import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
@XStreamAlias( "fleet" )
public class FleetInformation
implements Serializable
{
private static final long serialVersionUID = 1L;
@XStreamAsAttribute
private long id;
@XStreamAsAttribute
private String name;
@XStreamAsAttribute
private String status;
@XStreamAsAttribute
private boolean attacking;
@XStreamAlias( "location-id" )
private int locationId;
@XStreamAlias( "location-name" )
private String locationName;
@XStreamAlias( "ships" )
private List< ShipsInformation > ships = new LinkedList< ShipsInformation >( );
private MovementInformation movement;
public long getId( )
{
return id;
}
public void setId( long id )
{
this.id = id;
}
public String getName( )
{
return name;
}
public void setName( String name )
{
this.name = name;
}
public String getStatus( )
{
return status;
}
public void setStatus( String status )
{
this.status = status;
}
public boolean isAttacking( )
{
return attacking;
}
public void setAttacking( boolean attacking )
{
this.attacking = attacking;
}
public int getLocationId( )
{
return locationId;
}
public void setLocationId( int locationId )
{
this.locationId = locationId;
}
public String getLocationName( )
{
return locationName;
}
public void setLocationName( String locationName )
{
this.locationName = locationName;
}
public MovementInformation getMovement( )
{
return movement;
}
public void setMovement( MovementInformation movement )
{
this.movement = movement;
}
public List< ShipsInformation > getShips( )
{
return ships;
}
}

View file

@ -0,0 +1,157 @@
package com.deepclone.lw.beans.bt.esdata;
import java.io.Serializable;
import com.thoughtworks.xstream.annotations.XStreamAlias;
@XStreamAlias( "movement" )
public class MovementInformation
implements Serializable
{
private static final long serialVersionUID = 1L;
private int sourceId;
private String sourceName;
private int timeLeft;
private int stateTimeLeft;
private Float startX;
private Float startY;
private Integer nearId;
private String nearName;
private Boolean outwards;
private Boolean pastRefPoint;
public int getSourceId( )
{
return sourceId;
}
public void setSourceId( int sourceId )
{
this.sourceId = sourceId;
}
public String getSourceName( )
{
return sourceName;
}
public void setSourceName( String sourceName )
{
this.sourceName = sourceName;
}
public int getTimeLeft( )
{
return timeLeft;
}
public void setTimeLeft( int timeLeft )
{
this.timeLeft = timeLeft;
}
public int getStateTimeLeft( )
{
return stateTimeLeft;
}
public void setStateTimeLeft( int stateTimeLeft )
{
this.stateTimeLeft = stateTimeLeft;
}
public Float getStartX( )
{
return startX;
}
public void setStartX( Float startX )
{
this.startX = startX;
}
public Float getStartY( )
{
return startY;
}
public void setStartY( Float startY )
{
this.startY = startY;
}
public Integer getNearId( )
{
return nearId;
}
public void setNearId( Integer nearId )
{
this.nearId = nearId;
}
public String getNearName( )
{
return nearName;
}
public void setNearName( String nearName )
{
this.nearName = nearName;
}
public Boolean getOutwards( )
{
return outwards;
}
public void setOutwards( Boolean outwards )
{
this.outwards = outwards;
}
public Boolean getPastRefPoint( )
{
return pastRefPoint;
}
public void setPastRefPoint( Boolean pastRefPoint )
{
this.pastRefPoint = pastRefPoint;
}
}

View file

@ -0,0 +1,124 @@
package com.deepclone.lw.beans.bt.esdata;
import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
@XStreamAlias( "planet" )
public class PlanetInformation
implements Serializable
{
private static final long serialVersionUID = 1L;
@XStreamAsAttribute
@XStreamAlias( "id" )
private int id;
@XStreamAsAttribute
@XStreamAlias( "id" )
private String name;
@XStreamAlias( "population" )
private double population;
@XStreamAlias( "current-happiness" )
private double currentHappiness;
@XStreamAlias( "target-happiness" )
private double targetHappiness;
@XStreamAlias( "buildings" )
private List< BuildingsInformation > buildings = new LinkedList< BuildingsInformation >( );
@XStreamAlias( "civ-queue" )
private QueueInformation civilianQueue = new QueueInformation( );
@XStreamAlias( "mil-queue" )
private QueueInformation militaryQueue = new QueueInformation( );
public int getId( )
{
return id;
}
public void setId( int id )
{
this.id = id;
}
public String getName( )
{
return name;
}
public void setName( String name )
{
this.name = name;
}
public double getPopulation( )
{
return population;
}
public void setPopulation( double population )
{
this.population = population;
}
public double getCurrentHappiness( )
{
return currentHappiness;
}
public void setCurrentHappiness( double currentHappiness )
{
this.currentHappiness = currentHappiness;
}
public double getTargetHappiness( )
{
return targetHappiness;
}
public void setTargetHappiness( double targetHappiness )
{
this.targetHappiness = targetHappiness;
}
public List< BuildingsInformation > getBuildings( )
{
return buildings;
}
public QueueInformation getCivilianQueue( )
{
return civilianQueue;
}
public QueueInformation getMilitaryQueue( )
{
return militaryQueue;
}
}

View file

@ -0,0 +1,61 @@
package com.deepclone.lw.beans.bt.esdata;
import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
import com.thoughtworks.xstream.annotations.XStreamImplicit;
public class QueueInformation
implements Serializable
{
private static final long serialVersionUID = 1L;
@XStreamAsAttribute
@XStreamAlias( "accumulated-work" )
private double accWork;
@XStreamAsAttribute
@XStreamAlias( "accumulated-money" )
private double accMoney;
@XStreamImplicit( itemFieldName = "item" )
private List< QueueItemInformation > items = new LinkedList< QueueItemInformation >( );
public double getAccWork( )
{
return accWork;
}
public void setAccWork( double accWork )
{
this.accWork = accWork;
}
public double getAccMoney( )
{
return accMoney;
}
public void setAccMoney( double accMoney )
{
this.accMoney = accMoney;
}
public List< QueueItemInformation > getItems( )
{
return items;
}
}

View file

@ -0,0 +1,108 @@
package com.deepclone.lw.beans.bt.esdata;
import java.io.Serializable;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
public class QueueItemInformation
implements Serializable
{
private static final long serialVersionUID = 1L;
transient private int planetId;
transient private boolean military;
@XStreamAsAttribute
@XStreamAlias( "id" )
private int id;
@XStreamAsAttribute
@XStreamAlias( "name" )
private String name;
@XStreamAsAttribute
@XStreamAlias( "destroy" )
private boolean destroy;
@XStreamAsAttribute
@XStreamAlias( "amount" )
private int amount;
public int getPlanetId( )
{
return planetId;
}
public void setPlanetId( int planetId )
{
this.planetId = planetId;
}
public boolean isMilitary( )
{
return military;
}
public void setMilitary( boolean military )
{
this.military = military;
}
public int getId( )
{
return id;
}
public void setId( int id )
{
this.id = id;
}
public String getName( )
{
return name;
}
public void setName( String name )
{
this.name = name;
}
public boolean isDestroy( )
{
return destroy;
}
public void setDestroy( boolean destroy )
{
this.destroy = destroy;
}
public int getAmount( )
{
return amount;
}
public void setAmount( int amount )
{
this.amount = amount;
}
}

View file

@ -0,0 +1,83 @@
package com.deepclone.lw.beans.bt.esdata;
import java.io.Serializable;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
@XStreamAlias( "research-line" )
public class ResearchInformation
implements Serializable
{
private static final long serialVersionUID = 1L;
@XStreamAsAttribute
@XStreamAlias( "line")
private int id;
@XStreamAsAttribute
@XStreamAlias( "level")
private int currentLevel;
@XStreamAsAttribute
@XStreamAlias( "name")
private String levelName;
@XStreamAsAttribute
@XStreamAlias( "accumulated-points")
private double accumulated;
public int getId( )
{
return id;
}
public void setId( int id )
{
this.id = id;
}
public int getCurrentLevel( )
{
return currentLevel;
}
public void setCurrentLevel( int currentLevel )
{
this.currentLevel = currentLevel;
}
public String getLevelName( )
{
return levelName;
}
public void setLevelName( String levelName )
{
this.levelName = levelName;
}
public double getAccumulated( )
{
return accumulated;
}
public void setAccumulated( double accumulated )
{
this.accumulated = accumulated;
}
}

View file

@ -0,0 +1,96 @@
package com.deepclone.lw.beans.bt.esdata;
import java.io.Serializable;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
@XStreamAlias( "ship-type" )
public class ShipsInformation
implements Serializable
{
private static final long serialVersionUID = 1L;
transient private long fleetId;
@XStreamAsAttribute
@XStreamAlias( "id" )
private int id;
@XStreamAsAttribute
@XStreamAlias( "name" )
private String name;
@XStreamAsAttribute
@XStreamAlias( "amount" )
private long amount;
@XStreamAsAttribute
@XStreamAlias( "damage" )
private double damage;
public long getFleetId( )
{
return fleetId;
}
public void setFleetId( long fleetId )
{
this.fleetId = fleetId;
}
public int getId( )
{
return id;
}
public void setId( int id )
{
this.id = id;
}
public String getName( )
{
return name;
}
public void setName( String name )
{
this.name = name;
}
public long getAmount( )
{
return amount;
}
public void setAmount( long amount )
{
this.amount = amount;
}
public double getDamage( )
{
return damage;
}
public void setDamage( double damage )
{
this.damage = damage;
}
}

View file

@ -0,0 +1,50 @@
package com.deepclone.lw.beans.bt.esdata;
import java.io.Serializable;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
@XStreamAlias( "system-info" )
public class SystemInformation
implements Serializable
{
private static final long serialVersionUID = 1L;
@XStreamAsAttribute
@XStreamAlias( "computing-tick" )
private Long currentTick;
@XStreamAsAttribute
@XStreamAlias( "next-tick" )
private long nextTick;
public Long getCurrentTick( )
{
return currentTick;
}
public void setCurrentTick( Long currentTick )
{
this.currentTick = currentTick;
}
public long getNextTick( )
{
return nextTick;
}
public void setNextTick( long nextTick )
{
this.nextTick = nextTick;
}
}

View file

@ -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"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<import resource="bt/admin-bugs-bean.xml" />
<import resource="bt/bugs-dao-bean.xml" />
<import resource="bt/empire-summary-bean.xml" />
<import resource="bt/player-bugs-bean.xml" />
</beans>

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="adminBugs" class="com.deepclone.lw.beans.bt.AdminBugsBean" />
</beans>

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="bugsDAO" class="com.deepclone.lw.beans.bt.BugsDAOBean" />
</beans>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="empireSummary" class="com.deepclone.lw.beans.bt.EmpireSummaryBean" />
</beans>

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="playerBugs" class="com.deepclone.lw.beans.bt.PlayerBugsBean" />
</beans>

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java"/>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View file

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>legacyworlds-server-beans-eventlog</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.maven.ide.eclipse.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.maven.ide.eclipse.maven2Nature</nature>
</natures>
</projectDescription>

View file

@ -0,0 +1,6 @@
#Fri Apr 09 10:19:28 CEST 2010
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=1.6

View file

@ -0,0 +1,15 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>legacyworlds-server-beans</artifactId>
<groupId>com.deepclone.lw</groupId>
<version>5.99.1</version>
</parent>
<groupId>com.deepclone.lw</groupId>
<artifactId>legacyworlds-server-beans-eventlog</artifactId>
<version>5.99.1</version>
<name>Legacy Worlds event log</name>
<description>This package is responsible for all logging in Legacy Worlds through three different beans (system event logger, admin event logger and user event logger).</description>
</project>

View file

@ -0,0 +1,80 @@
package com.deepclone.lw.beans.eventlog;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.support.TransactionTemplate;
import com.deepclone.lw.interfaces.admin.AdminDAO;
import com.deepclone.lw.interfaces.eventlog.LogReader;
import com.deepclone.lw.interfaces.mailer.Mailer;
import com.deepclone.lw.interfaces.sys.Ticker;
import com.deepclone.lw.interfaces.sys.Ticker.Frequency;
public class AdminErrorMailBean
implements InitializingBean , DisposableBean
{
private Ticker ticker;
private LogReader logReader;
private AdminDAO adminDao;
private TransactionTemplate tTemplate;
private Mailer mailer;
private AdminErrorMailTask task;
@Autowired( required = true )
public void setTicker( Ticker ticker )
{
this.ticker = ticker;
}
@Autowired( required = true )
public void setLogReader( LogReader logReader )
{
this.logReader = logReader;
}
@Autowired( required = true )
public void setAdminDao( AdminDAO adminDao )
{
this.adminDao = adminDao;
}
@Autowired( required = true )
public void setTransactionManager( PlatformTransactionManager tManager )
{
this.tTemplate = new TransactionTemplate( tManager );
}
@Autowired( required = true )
public void setMailer( Mailer mailer )
{
this.mailer = mailer;
}
@Override
public void afterPropertiesSet( )
{
this.task = new AdminErrorMailTask( this.adminDao , this.logReader , this.mailer , this.tTemplate );
this.ticker.registerTask( Frequency.LOW , "Admin error mail sender" , this.task );
}
@Override
public void destroy( )
{
this.task = null;
}
}

View file

@ -0,0 +1,135 @@
package com.deepclone.lw.beans.eventlog;
import java.text.SimpleDateFormat;
import java.util.LinkedList;
import java.util.List;
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.cmd.admin.logs.ExceptionEntry;
import com.deepclone.lw.cmd.admin.logs.TraceEntry;
import com.deepclone.lw.interfaces.admin.AdminDAO;
import com.deepclone.lw.interfaces.eventlog.ExtendedLogEntry;
import com.deepclone.lw.interfaces.eventlog.LogReader;
import com.deepclone.lw.interfaces.mailer.MailData;
import com.deepclone.lw.interfaces.mailer.Mailer;
import com.deepclone.lw.sqld.admin.AdminRecord;
class AdminErrorMailTask
implements Runnable
{
private static class ErrorData
{
public final List< AdminRecord > administrators;
public final List< ExtendedLogEntry > logEntries;
public ErrorData( List< AdminRecord > administrators , List< ExtendedLogEntry > logEntries )
{
this.administrators = administrators;
this.logEntries = logEntries;
}
}
private final TransactionTemplate tTemplate;
private final AdminDAO adminDao;
private final LogReader logReader;
private final Mailer mailer;
public AdminErrorMailTask( AdminDAO adminDao , LogReader logReader , Mailer mailer , TransactionTemplate tTemplate )
{
this.adminDao = adminDao;
this.logReader = logReader;
this.mailer = mailer;
this.tTemplate = tTemplate;
}
@Override
public void run( )
{
// Get errors and administrators
ErrorData errorData;
errorData = this.tTemplate.execute( new TransactionCallback< ErrorData >( ) {
@Override
public ErrorData doInTransaction( TransactionStatus status )
{
return getErrorData( );
}
} );
// No receiving administrators or no errors -> exit
if ( errorData.administrators.isEmpty( ) || errorData.logEntries.isEmpty( ) ) {
return;
}
// Generate message contents
String message = this.buildMessage( errorData.logEntries );
for ( AdminRecord admin : errorData.administrators ) {
try {
MailData mail = this.mailer.createMail( "en" , "adminErrorMail" , admin.getAddress( ) );
mail.setData( "contents" , message );
mail.queue( );
} catch ( Exception e ) {
throw new RuntimeException( e );
}
}
}
private ErrorData getErrorData( )
{
List< AdminRecord > admins = new LinkedList< AdminRecord >( );
for ( AdminRecord admin : this.adminDao.listAdministrators( ) ) {
if ( Privileges.BUGM.hasPrivilege( admin.getPrivileges( ) ) ) {
admins.add( admin );
}
}
return new ErrorData( admins , this.logReader.getErrorEntries( ) );
}
private String buildMessage( List< ExtendedLogEntry > logEntries )
{
StringBuilder builder = new StringBuilder( );
SimpleDateFormat dFmt = new SimpleDateFormat( "yyyy-MM-dd" );
SimpleDateFormat tFmt = new SimpleDateFormat( "HH:mm:ss" );
for ( ExtendedLogEntry entry : logEntries ) {
builder.append( "Date: " ).append( dFmt.format( entry.logEntry.getTimestamp( ) ) );
builder.append( "\nTime: " ).append( tFmt.format( entry.logEntry.getTimestamp( ) ) );
builder.append( "\nComponent: " ).append( entry.logEntry.getAbout( ) );
builder.append( "\nMessage: " ).append( entry.logEntry.getEntry( ) ).append( "\n" );
for ( ExceptionEntry eEntry : entry.exceptions ) {
builder.append( "\n " ).append( eEntry.getClassName( ) );
if ( eEntry.getMessage( ) != null && !"".equals( eEntry ) ) {
builder.append( ": " ).append( eEntry.getMessage( ) );
}
int i = 0;
for ( TraceEntry tEntry : eEntry.getTrace( ) ) {
builder.append( "\n " );
if ( i++ > 5 ) {
builder.append( "..." );
break;
}
builder.append( tEntry.getLocation( ) );
}
}
builder.append( "\n\n\n" );
}
return builder.toString( );
}
}

View file

@ -0,0 +1,34 @@
package com.deepclone.lw.beans.eventlog;
import com.deepclone.lw.sqld.sys.SystemLogEntry;
/**
* Log writer queue entries only carry a log entry, which may be null to indicate that the log
* writer's task must be terminated.
*
* @author tseeker
*/
class EntryQueueItem
{
/** The log entry */
final SystemLogEntry entry;
/** Initialises a "termination" queue entry */
EntryQueueItem( )
{
this.entry = null;
}
/** Initialises a log-carrying queue entry */
EntryQueueItem( SystemLogEntry entry )
{
this.entry = entry;
}
}

View file

@ -0,0 +1,107 @@
package com.deepclone.lw.beans.eventlog;
import javax.sql.DataSource;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.PlatformTransactionManager;
import com.deepclone.lw.interfaces.sys.Ticker;
import com.deepclone.lw.interfaces.sys.Ticker.Frequency;
/**
* Log clean-up bean.
*
* <p>
* This bean is responsible for removing old log entries from the various logging tables. It
* registers a set of constants which determine the maximal age of a log entry depending on its
* category (administrative, account or system) and starts a ticker task with a high frequency.
*
* @author tseeker
*
*/
public class LogCleanerBean
implements InitializingBean , DisposableBean
{
/** Ticker bean */
private Ticker ticker;
/** Transaction manager */
private PlatformTransactionManager transactionManager;
/** Log cleaner task instance */
private LogCleanerTask cleanerTask;
private DataSource dataSource;
/**
* Sets the ticker bean reference (DI).
*
* @param ticker
* the ticker bean
*/
@Autowired( required = true )
public void setTicker( Ticker ticker )
{
this.ticker = ticker;
}
/**
* Sets the transaction manager reference (DI).
*
* @param manager
* the transaction manager
*/
@Autowired( required = true )
public void setTransactionManager( PlatformTransactionManager manager )
{
this.transactionManager = manager;
}
@Autowired( required = true )
public void setDataSource( DataSource dataSource )
{
this.dataSource = dataSource;
}
/**
* Registers constants and initialises the log clean-up task.
*
* <p>
* Once the dependencies have been injected, this method will register the
* <em>log.maxAge.admin</em>, <em>log.maxAge.account</em> and <em>log.maxAge.system</em>
* constants, setting their default values to 7 days. It will then create the clean-up task
* instance, register it as a constants user, and add it to the ticker with a high frequency.
*/
@Override
public void afterPropertiesSet( )
{
// Create clean-up task
this.cleanerTask = new LogCleanerTask( this.dataSource , this.transactionManager );
this.ticker.registerTask( Frequency.LOW , "Log cleaner" , this.cleanerTask );
}
/**
* Removes references to the clean-up task.
*
* <p>
* Before the bean is destroyed, this method will unregister the clean-up task from the
* constants manager and remove the local reference.
*/
@Override
public void destroy( )
{
this.cleanerTask = null;
}
}

View file

@ -0,0 +1,61 @@
package com.deepclone.lw.beans.eventlog;
import javax.sql.DataSource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
/**
* Log clean-up task.
*
* <p>
* This class implements the log clean-up task; it is simultaneously a constants user (as it needs
* to keep informed about <em>log.maxAge.*</em>), a runnable (as it needs to be registered as a
* ticker task) and a transaction callback (to perform the actual clean-up).
*
* @author tseeker
*/
class LogCleanerTask
implements Runnable
{
/** Transaction manager interface */
private final TransactionTemplate tTemplate;
private JdbcTemplate dTemplate;
/**
* @param sessionFactory
* the Hibernate session factory
* @param transactionManager
* the transaction manager
*/
LogCleanerTask( DataSource dataSource , PlatformTransactionManager transactionManager )
{
this.tTemplate = new TransactionTemplate( transactionManager );
this.dTemplate = new JdbcTemplate( dataSource );
}
/**
* Executes the clean-up transaction if the constants have been set.
*/
@Override
synchronized public void run( )
{
this.tTemplate.execute( new TransactionCallbackWithoutResult( ) {
@Override
protected void doInTransactionWithoutResult( TransactionStatus status )
{
dTemplate.execute( "SELECT sys.clean_logs( )" );
}
} );
}
}

View file

@ -0,0 +1,284 @@
package com.deepclone.lw.beans.eventlog;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
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.cmd.admin.adata.Administrator;
import com.deepclone.lw.cmd.admin.logs.ExceptionEntry;
import com.deepclone.lw.cmd.admin.logs.GetEntryResponse;
import com.deepclone.lw.cmd.admin.logs.LogEntry;
import com.deepclone.lw.cmd.admin.logs.LogLevel;
import com.deepclone.lw.cmd.admin.logs.LogType;
import com.deepclone.lw.cmd.admin.logs.TraceEntry;
import com.deepclone.lw.cmd.admin.logs.ViewLogResponse;
import com.deepclone.lw.interfaces.eventlog.ExtendedLogEntry;
import com.deepclone.lw.interfaces.eventlog.LogReader;
import com.deepclone.lw.sqld.sys.ExceptionLog;
import com.deepclone.lw.sqld.sys.StackTraceLog;
public class LogReaderBean
implements LogReader
{
private SimpleJdbcTemplate dTemplate;
private TransactionTemplate tTemplate;
private final RowMapper< LogEntry > mLogEntry;
private final RowMapper< ExceptionLog > mExceptionLog;
private final RowMapper< StackTraceLog > mTraceLog;
public LogReaderBean( )
{
this.mLogEntry = new RowMapper< LogEntry >( ) {
@Override
public LogEntry mapRow( ResultSet rs , int rowNum )
throws SQLException
{
LogEntry entry = new LogEntry( );
entry.setId( (Long) rs.getObject( "id" ) );
entry.setTimestamp( rs.getTimestamp( "t" ) );
entry.setAbout( rs.getString( "component" ) );
entry.setLevel( LogLevel.valueOf( rs.getString( "level" ) ) );
entry.setEntry( rs.getString( "message" ) );
entry.setException( (Long) rs.getObject( "exception_id" ) );
return entry;
}
};
this.mExceptionLog = new RowMapper< ExceptionLog >( ) {
@Override
public ExceptionLog mapRow( ResultSet rs , int rowNum )
throws SQLException
{
return new ExceptionLog( rs.getLong( "id" ) , rs.getInt( "depth" ) , rs.getString( "exc_class" ) , rs
.getString( "message" ) );
}
};
this.mTraceLog = new RowMapper< StackTraceLog >( ) {
@Override
public StackTraceLog mapRow( ResultSet rs , int rowNum )
throws SQLException
{
return new StackTraceLog( rs.getLong( "exception_id" ) , rs.getInt( "depth" ) , rs
.getString( "location" ) , rs.getString( "file_name" ) , (Integer) rs.getObject( "line_number" ) );
}
};
}
@Autowired( required = true )
public void setDataSource( DataSource dataSource )
{
this.dTemplate = new SimpleJdbcTemplate( dataSource );
}
@Autowired( required = true )
public void setTransactionManager( PlatformTransactionManager tManager )
{
this.tTemplate = new TransactionTemplate( tManager );
}
@Override
public ViewLogResponse getLog( final Administrator admin , final LogType type , final long first , final int count ,
final LogLevel minLevel , final String component , final boolean excOnly )
{
if ( excOnly && type != LogType.SYSTEM ) {
return new ViewLogResponse( admin , 0 , new LinkedList< LogEntry >( ) );
}
return this.tTemplate.execute( new TransactionCallback< ViewLogResponse >( ) {
@Override
public ViewLogResponse doInTransaction( TransactionStatus status )
{
return getLogQueries( admin , type , first , count , minLevel , component , excOnly );
}
} );
}
private ViewLogResponse getLogQueries( Administrator admin , LogType type , long first , int count ,
LogLevel minLevel , String component , boolean excOnly )
{
String countQuery = this.buildQuery( true , type , first , count , minLevel , component , excOnly );
Object[] cqParams = this.buildQueryParams( true , first , count , minLevel , component );
long nEntries = this.dTemplate.queryForLong( countQuery , cqParams );
String mainQuery = this.buildQuery( false , type , first , count , minLevel , component , excOnly );
Object[] mqParams = this.buildQueryParams( false , first , count , minLevel , component );
List< LogEntry > entries = this.dTemplate.query( mainQuery , this.mLogEntry , mqParams );
return new ViewLogResponse( admin , nEntries , entries );
}
private Object[] buildQueryParams( boolean isCount , long first , int count , LogLevel minLevel , String component )
{
boolean hasComponent = ( component != null && !"".equals( component ) );
Object[] params = new Object[ ( hasComponent ? 2 : 1 ) + ( isCount ? 0 : 2 ) ];
int i = 0;
params[ i++ ] = minLevel.toString( );
if ( hasComponent ) {
params[ i++ ] = "%" + component + "%";
}
if ( !isCount ) {
params[ i++ ] = (Long) first;
params[ i++ ] = (Integer) count;
}
return params;
}
private String buildQuery( boolean isCount , LogType type , long first , int count , LogLevel minLevel ,
String component , boolean excOnly )
{
StringBuilder builder = new StringBuilder( );
// Selection from the right view
builder.append( "SELECT " );
if ( isCount ) {
builder.append( "count(*)" );
} else {
builder.append( "*" );
}
builder.append( " FROM sys." ).append( type.toString( ).toLowerCase( ) ).append( "_logs_view WHERE " );
// Minimal log level
builder.append( "level >= ?::log_level" );
// Component
if ( component != null && !"".equals( component ) ) {
builder.append( " AND lower( component ) LIKE ?" );
}
// Exception only
if ( excOnly ) {
builder.append( " AND exception_id IS NOT NULL" );
}
if ( !isCount ) {
// Ordering, index, count
builder.append( " ORDER BY t DESC OFFSET ? LIMIT ?" );
}
return builder.toString( );
}
@Override
public GetEntryResponse getEntry( final Administrator admin , final long id )
{
return this.tTemplate.execute( new TransactionCallback< GetEntryResponse >( ) {
@Override
public GetEntryResponse doInTransaction( TransactionStatus status )
{
return doGetEntryResponse( admin , id );
}
} );
}
private GetEntryResponse doGetEntryResponse( Administrator admin , long id )
{
ExtendedLogEntry lEntry = this.doGetEntry( id );
if ( lEntry == null ) {
return new GetEntryResponse( admin , false );
}
return new GetEntryResponse( admin , lEntry.logEntry , lEntry.exceptions );
}
private ExtendedLogEntry doGetEntry( long id )
{
String sql = "SELECT * FROM sys.system_logs_view WHERE id = ?";
// Get log entry
LogEntry entry;
try {
entry = this.dTemplate.queryForObject( sql , this.mLogEntry , id );
} catch ( EmptyResultDataAccessException e ) {
return null;
}
// Get exceptions
List< ExceptionLog > eLog;
sql = "SELECT * FROM sys.exceptions WHERE log_id = ? ORDER BY depth";
eLog = this.dTemplate.query( sql , this.mExceptionLog , id );
Map< Long , ExceptionLog > eLogId = new HashMap< Long , ExceptionLog >( );
for ( ExceptionLog ee : eLog ) {
eLogId.put( ee.getId( ) , ee );
}
// Get stack trace entries
sql = "SELECT st.* FROM sys.stack_traces st INNER JOIN sys.exceptions e ON e.id = st.exception_id WHERE e.log_id = ? ORDER BY st.depth DESC";
for ( StackTraceLog stLog : this.dTemplate.query( sql , this.mTraceLog , id ) ) {
ExceptionLog ee = eLogId.get( stLog.getExcId( ) );
ee.addStackTrace( stLog );
}
// Generate output
List< ExceptionEntry > exceptions = new LinkedList< ExceptionEntry >( );
for ( ExceptionLog ee : eLog ) {
ExceptionEntry eEntry = new ExceptionEntry( ee.getClassName( ) , ee.getMessage( ) );
List< TraceEntry > stackTrace = new LinkedList< TraceEntry >( );
for ( StackTraceLog stLog : ee.getStack( ) ) {
stackTrace.add( new TraceEntry( stLog.getLocation( ) , stLog.getFileName( ) , stLog.getLine( ) ) );
}
eEntry.setTrace( stackTrace );
exceptions.add( eEntry );
}
return new ExtendedLogEntry( entry , exceptions );
}
@Override
public List< ExtendedLogEntry > getErrorEntries( )
{
List< ExtendedLogEntry > result = new LinkedList< ExtendedLogEntry >( );
String sql = "SELECT * FROM admin.get_error_entries( )";
RowMapper< Long > longLister = new RowMapper< Long >( ) {
@Override
public Long mapRow( ResultSet rs , int rowNum )
throws SQLException
{
return rs.getLong( 1 );
}
};
for ( Long id : this.dTemplate.query( sql , longLister ) ) {
result.add( this.doGetEntry( id ) );
}
return result;
}
@Override
public List< LogEntry > getAdminLogSince( Timestamp timestamp )
{
String sql = "SELECT * FROM sys.admin_logs_view WHERE t >= ? AND level >= 'INFO'::log_level ORDER BY t DESC";
return this.dTemplate.query( sql , this.mLogEntry , timestamp );
}
}

View file

@ -0,0 +1,122 @@
package com.deepclone.lw.beans.eventlog;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
import javax.sql.DataSource;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.support.TransactionTemplate;
import com.deepclone.lw.interfaces.eventlog.LogWriter;
import com.deepclone.lw.sqld.sys.SystemLogEntry;
/**
* The log writer bean, once initialised, spawns a task while continuously examines a blocking
* queue. When entries are added to the queue, they are flushed to the database. When the bean
* container destroys the bean, a queue entry carrying the null value is added to the queue, causing
* the task to terminate.
*
* @author tseeker
*
*/
public class LogWriterBean
implements LogWriter , InitializingBean , DisposableBean
{
/** Transaction management instance */
private TransactionTemplate tTemplate;
/** JDBC data source */
private DataSource dataSource;
/** The queue used for log entries */
private LinkedBlockingQueue< EntryQueueItem > queue = null;
/**
* Sets the JDBC data source (DI)
*
* @param dataSource
* the JDBC data source
*/
@Autowired( required = true )
public void setDataSource( DataSource dataSource )
{
this.dataSource = dataSource;
}
/**
* Initialises the interface to the transaction manager (DI)
*
* @param manager
* the transaction manager to use
*/
@Autowired( required = true )
public void setTransactionManager( PlatformTransactionManager manager )
{
this.tTemplate = new TransactionTemplate( manager );
}
/* Documentation in LogWriter interface */
@Override
synchronized public void addEntries( List< SystemLogEntry > entries )
{
if ( this.queue == null ) {
return;
}
LinkedList< EntryQueueItem > items = new LinkedList< EntryQueueItem >( );
for ( SystemLogEntry e : entries ) {
if ( e == null ) {
continue;
}
items.add( new EntryQueueItem( e ) );
}
this.queue.addAll( items );
}
/**
* Bean initialisation - creates the queue and spawns the log writer task.
*/
@Override
public void afterPropertiesSet( )
{
this.queue = new LinkedBlockingQueue< EntryQueueItem >( );
LogWriterTask task;
task = new LogWriterTask( this.queue , this.dataSource , this.tTemplate );
Thread t;
t = new Thread( task );
t.start( );
}
/**
* Bean destruction - inserts a null entry on the log writer queue, then waits for the task to
* terminate.
*/
@Override
public void destroy( )
{
this.queue.add( new EntryQueueItem( ) );
while ( !this.queue.isEmpty( ) ) {
Thread.yield( );
}
synchronized ( this ) {
this.queue = null;
}
}
}

View file

@ -0,0 +1,166 @@
package com.deepclone.lw.beans.eventlog;
import java.sql.Types;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
import javax.sql.DataSource;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.transaction.CannotCreateTransactionException;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import com.deepclone.lw.sqld.sys.ExceptionLog;
import com.deepclone.lw.sqld.sys.StackTraceLog;
import com.deepclone.lw.sqld.sys.SystemLogEntry;
import com.deepclone.lw.utils.StoredProc;
/**
* The log writer task is spawned by the log writer bean. Whenever log entries are pushed to the log
* writer, they are added to a queue which this tasks continuously reads. If a queue item carrying
* the null value is found, the queue is flushed and the task terminates.
*
* @author tseeker
*/
class LogWriterTask
implements Runnable
{
/** The queue */
private final LinkedBlockingQueue< EntryQueueItem > queue;
/** Transaction management interface */
private final TransactionTemplate tTemplate;
private StoredProc fLog;
private StoredProc fException;
private StoredProc fTrace;
/** Copies the required references */
LogWriterTask( LinkedBlockingQueue< EntryQueueItem > queue , DataSource dataSource , TransactionTemplate tTemplate )
{
this.queue = queue;
this.tTemplate = tTemplate;
this.fLog = new StoredProc( dataSource , "sys" , "write_log" );
this.fLog.addParameter( "component" , Types.VARCHAR );
this.fLog.addParameter( "level" , "log_level" );
this.fLog.addParameter( "message" , Types.VARCHAR );
this.fLog.addOutput( "entry_id" , Types.BIGINT );
this.fException = new StoredProc( dataSource , "sys" , "append_exception" );
this.fException.addParameter( "log_id" , Types.BIGINT );
this.fException.addParameter( "class_name" , Types.VARCHAR );
this.fException.addParameter( "message" , Types.VARCHAR );
this.fException.addOutput( "entry_id" , Types.BIGINT );
this.fTrace = new StoredProc( dataSource , "sys" , "append_trace" );
this.fTrace.addParameter( "exc_id" , Types.BIGINT );
this.fTrace.addParameter( "location" , Types.VARCHAR );
this.fTrace.addParameter( "file_name" , Types.VARCHAR );
this.fTrace.addParameter( "line_number" , Types.INTEGER );
}
/**
* Implements the consumer side of the queue; when an item is found, all items are flushed and
* written to the DB in the same transaction.
*/
@Override
public void run( )
{
boolean keepRunning = true;
while ( keepRunning ) {
LinkedList< EntryQueueItem > items;
items = new LinkedList< EntryQueueItem >( );
// Wait for the next queue entry
EntryQueueItem item;
try {
item = this.queue.take( );
} catch ( InterruptedException e ) {
continue;
}
// Take everything else on the queue
this.queue.drainTo( items );
items.add( item );
// Process the items obtained from the queue, watching for null values as they will
// interrupt the task
final LinkedList< SystemLogEntry > okItems = new LinkedList< SystemLogEntry >( );
for ( EntryQueueItem i : items ) {
if ( i.entry == null ) {
keepRunning = false;
} else {
okItems.add( i.entry );
}
}
// If there's nothing to write, restart the loop (that usually means we're being
// terminated)
if ( okItems.isEmpty( ) ) {
continue;
}
// Try writing to the DB
boolean writeSuccess = false;
while ( ! writeSuccess ) {
try {
this.tTemplate.execute( new TransactionCallbackWithoutResult( ) {
@Override
protected void doInTransactionWithoutResult( TransactionStatus status )
{
writeLogEntries( okItems );
}
} );
writeSuccess = true;
} catch ( DataAccessResourceFailureException e ) {
// Do nothing
} catch ( CannotCreateTransactionException e ) {
// Do nothing
}
if (! writeSuccess ) {
if ( !this.queue.isEmpty( ) ) {
// If there is stuff in the queue, abort writing.
// We might actually need to exit.
break;
}
try {
Thread.sleep( 2000 );
} catch ( InterruptedException e1 ) {
break;
}
}
}
}
}
private void writeLogEntries( List< SystemLogEntry > entries )
{
for ( SystemLogEntry entry : entries ) {
Long id = (Long) this.fLog.execute( entry.getComponent( ) , entry.getLevel( ).toString( ) ,
entry.getMessage( ) ).get( "entry_id" );
for ( ExceptionLog exc : entry.getException( ) ) {
Long eid = (Long) this.fException.execute( id , exc.getClassName( ) , exc.getMessage( ) ).get(
"entry_id" );
for ( StackTraceLog st : exc.getStack( ) ) {
this.fTrace.execute( eid , st.getLocation( ) , st.getFileName( ) , st.getLine( ) );
}
}
}
}
}

View file

@ -0,0 +1,61 @@
package com.deepclone.lw.beans.eventlog;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import com.deepclone.lw.interfaces.eventlog.LogWriter;
import com.deepclone.lw.interfaces.eventlog.Logger;
import com.deepclone.lw.interfaces.eventlog.SystemLogger;
import com.deepclone.lw.sqld.sys.SystemLogEntry;
/**
* The logger bean can be used to generate the various types of log entry generators. It
* communicates with a log writer to which entries produced by the generators will be flushed.
*
* @author tseeker
*
*/
public class LoggerBean
implements Logger
{
/** The log writer bean this logger pushes entries to */
private LogWriter logWriter;
/**
* Sets the log writer bean (DI)
*
* @param logWriter
* the log writer bean to push entries to
*/
@Autowired( required = true )
public void setLogWriter( LogWriter logWriter )
{
this.logWriter = logWriter;
}
/**
* Pushes a set of log entries to the log writer.
*
* @param entries
* the list of log entries to push
*/
void flush( List< SystemLogEntry > entries )
{
this.logWriter.addEntries( entries );
}
/* Documentation in Logger interface */
@Override
public SystemLogger getSystemLogger( String component )
{
return new SystemLoggerImpl( this , component );
}
}

View file

@ -0,0 +1,183 @@
package com.deepclone.lw.beans.eventlog;
import java.util.LinkedList;
import java.util.List;
import org.apache.log4j.Logger;
import com.deepclone.lw.cmd.admin.logs.LogLevel;
import com.deepclone.lw.interfaces.eventlog.SystemLogger;
import com.deepclone.lw.sqld.sys.ExceptionLog;
import com.deepclone.lw.sqld.sys.StackTraceLog;
import com.deepclone.lw.sqld.sys.SystemLogEntry;
/**
* The system logger implementation generates {@link SystemLogEntry} instances, setting their fields
* to the proper values and parsing exceptions as required. When flushed it simply uses the logger
* bean's flush() method to push its contents to the log writer.
*
* @author tseeker
*/
class SystemLoggerImpl
implements SystemLogger
{
/** External (log4j) logger */
private final Logger l4j = Logger.getLogger( SystemLogger.class );
/** The logger bean */
private final LoggerBean logger;
/** The name of the component this system logger is used by */
private final String component;
/** The list of entries that have been created but that haven't been flushed to the logger bean */
private List< SystemLogEntry > entries = new LinkedList< SystemLogEntry >( );
/** Stores the logger bean reference and the component's name */
SystemLoggerImpl( LoggerBean logger , String component )
{
this.logger = logger;
this.component = component;
}
/* Documentation in SystemLogger interface */
@Override
public SystemLogger flush( )
{
synchronized ( this.entries ) {
if ( !this.entries.isEmpty( ) ) {
this.logger.flush( this.entries );
this.entries.clear( );
}
}
return this;
}
/* Documentation in SystemLogger interface */
@Override
public SystemLogger log( LogLevel level , String message )
{
this.toLog4j( level , message , null );
SystemLogEntry entry = this.makeEntry( level , message );
synchronized ( this.entries ) {
this.entries.add( entry );
}
return this;
}
/* Documentation in SystemLogger interface */
@Override
public SystemLogger log( LogLevel level , String message , Throwable exception )
{
this.toLog4j( level , message , exception );
SystemLogEntry entry = this.makeEntry( level , message );
this.parseException( entry , exception );
synchronized ( this.entries ) {
this.entries.add( entry );
}
return this;
}
/**
* Logs a message through Log4J (in addition to the DB log).
*
* @param level
* log level
* @param message
* message to log
* @param exception
* optional exception to log along with the message
*/
private void toLog4j( LogLevel level , String message , Throwable exception )
{
message = this.component + " - " + message;
switch ( level ) {
case DEBUG:
this.l4j.debug( message , exception );
break;
case ERROR:
this.l4j.error( message , exception );
break;
case INFO:
this.l4j.info( message , exception );
break;
case TRACE:
this.l4j.trace( message , exception );
break;
case WARNING:
this.l4j.warn( message , exception );
break;
}
}
/**
* Generates the basic contents of a log entry using a log level and message
*
* @param level
* the entry's log level
* @param message
* the entry's message
* @return a fully usable {@link SystemLogEntry} instance
*/
private SystemLogEntry makeEntry( LogLevel level , String message )
{
return new SystemLogEntry( level , this.component , message );
}
/**
* Parses the specified exception so that the ExceptionLog instance and associated data can
* later be retrieved.
*
* @param exception
* the exception to parse
*/
private void parseException( SystemLogEntry logEntry , Throwable exception )
{
do {
ExceptionLog excData;
excData = new ExceptionLog( logEntry , exception.getClass( ).getCanonicalName( ) , exception.getMessage( ) );
this.parseTrace( excData , exception );
exception = exception.getCause( );
} while ( exception != null );
}
/**
* This method converts an exception's stack trace into TracebackLog instances, adding them to
* the list of associated objects and returning the top-most item.
*
* @param logData
* the exception's log entry
* @param exception
* the exception whose stack trace is to be converted
*/
private void parseTrace( ExceptionLog logData , Throwable exception )
{
StackTraceElement[] trace = exception.getStackTrace( );
for ( int i = trace.length - 1 ; i >= 0 ; i-- ) {
StackTraceElement e = trace[ i ];
new StackTraceLog( logData , e.getClassName( ) + "." + e.getMethodName( ) , e.getFileName( ) , e
.getLineNumber( ) );
}
}
}

Some files were not shown because too many files have changed in this diff Show more