diff --git a/org.eclipse.emf.cdo.server.db/.classpath b/org.eclipse.emf.cdo.server.db/.classpath
new file mode 100644
index 0000000..64c5e31
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/org.eclipse.emf.cdo.server.db/.options b/org.eclipse.emf.cdo.server.db/.options
new file mode 100644
index 0000000..f4f74f8
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/.options
@@ -0,0 +1,3 @@
+# Debugging and tracing options
+
+org.eclipse.emf.cdo.server.db/debug = true
diff --git a/org.eclipse.emf.cdo.server.db/.project b/org.eclipse.emf.cdo.server.db/.project
new file mode 100644
index 0000000..4bb79d4
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/.project
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.emf.cdo.server.db</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.api.tools.apiAnalysisBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.emf.cdo.releng.version.VersionBuilder</name>
+			<arguments>
+				<dictionary>
+					<key>release.path</key>
+					<value>/org.eclipse.emf.cdo.releng/release.xml</value>
+				</dictionary>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.pde.api.tools.apiAnalysisNature</nature>
+		<nature>org.eclipse.emf.cdo.releng.version.VersionNature</nature>
+	</natures>
+</projectDescription>
diff --git a/org.eclipse.emf.cdo.server.db/.settings/.api_filters b/org.eclipse.emf.cdo.server.db/.settings/.api_filters
new file mode 100644
index 0000000..475cf59
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/.settings/.api_filters
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>

+<component id="org.eclipse.emf.cdo.server.db" version="2">

+    <resource path="src/org/eclipse/emf/cdo/server/internal/db/DBStoreAccessor.java" type="org.eclipse.emf.cdo.server.internal.db.DBStoreAccessor">

+        <filter id="574660632">

+            <message_arguments>

+                <message_argument value="DurableLocking"/>

+                <message_argument value="IDurableLockingManager"/>

+                <message_argument value="DBStoreAccessor"/>

+            </message_arguments>

+        </filter>

+    </resource>

+</component>

diff --git a/org.eclipse.emf.cdo.server.db/.settings/org.eclipse.core.resources.prefs b/org.eclipse.emf.cdo.server.db/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..eca460f
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Mon Jul 04 13:01:28 CEST 2011

+eclipse.preferences.version=1

+encoding//model/org.eclipse.emf.cdo.defs.ecorediag=UTF-8

diff --git a/org.eclipse.emf.cdo.server.db/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.emf.cdo.server.db/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..611d1a9
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,373 @@
+#Fri Sep 02 05:40:11 CEST 2011

+eclipse.preferences.version=1

+org.eclipse.jdt.core.builder.cleanOutputFolder=clean

+org.eclipse.jdt.core.builder.duplicateResourceTask=warning

+org.eclipse.jdt.core.builder.invalidClasspath=abort

+org.eclipse.jdt.core.builder.recreateModifiedClassFileInOutputFolder=ignore

+org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch,*.ucls,doc-files/,package.html,package-info.java

+org.eclipse.jdt.core.circularClasspath=error

+org.eclipse.jdt.core.classpath.exclusionPatterns=enabled

+org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled

+org.eclipse.jdt.core.codeComplete.argumentPrefixes=

+org.eclipse.jdt.core.codeComplete.argumentSuffixes=

+org.eclipse.jdt.core.codeComplete.fieldPrefixes=

+org.eclipse.jdt.core.codeComplete.fieldSuffixes=

+org.eclipse.jdt.core.codeComplete.localPrefixes=

+org.eclipse.jdt.core.codeComplete.localSuffixes=

+org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=

+org.eclipse.jdt.core.codeComplete.staticFieldSuffixes=

+org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes=

+org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes=

+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled

+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5

+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve

+org.eclipse.jdt.core.compiler.compliance=1.5

+org.eclipse.jdt.core.compiler.debug.lineNumber=generate

+org.eclipse.jdt.core.compiler.debug.localVariable=generate

+org.eclipse.jdt.core.compiler.debug.sourceFile=generate

+org.eclipse.jdt.core.compiler.doc.comment.support=enabled

+org.eclipse.jdt.core.compiler.maxProblemPerUnit=100

+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning

+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error

+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore

+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning

+org.eclipse.jdt.core.compiler.problem.deadCode=warning

+org.eclipse.jdt.core.compiler.problem.deprecation=warning

+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled

+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=enabled

+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning

+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning

+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error

+org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning

+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled

+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore

+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning

+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning

+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error

+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning

+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled

+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning

+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore

+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore

+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning

+org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled

+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=disabled

+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=disabled

+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=public

+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore

+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning

+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning

+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning

+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore

+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled

+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public

+org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=return_tag

+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore

+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled

+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public

+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning

+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled

+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning

+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=warning

+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning

+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning

+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore

+org.eclipse.jdt.core.compiler.problem.nullReference=warning

+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning

+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore

+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning

+org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore

+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning

+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning

+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning

+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled

+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning

+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled

+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled

+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore

+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning

+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning

+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore

+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning

+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning

+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning

+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore

+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore

+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled

+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled

+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled

+org.eclipse.jdt.core.compiler.problem.unusedImport=warning

+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning

+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning

+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore

+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore

+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled

+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled

+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled

+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning

+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning

+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning

+org.eclipse.jdt.core.compiler.source=1.5

+org.eclipse.jdt.core.compiler.taskCaseSensitive=enabled

+org.eclipse.jdt.core.compiler.taskPriorities=NORMAL,HIGH,HIGH,LOW,LOW,LOW,LOW,LOW

+org.eclipse.jdt.core.compiler.taskTags=TODO,FIXME,XXX,PERF,MEM,POLISH,@generated NOT,@ADDED

+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false

+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16

+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16

+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16

+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16

+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16

+org.eclipse.jdt.core.formatter.alignment_for_assignment=0

+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16

+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16

+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80

+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0

+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16

+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16

+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16

+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16

+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16

+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16

+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16

+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16

+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16

+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16

+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1

+org.eclipse.jdt.core.formatter.blank_lines_after_package=1

+org.eclipse.jdt.core.formatter.blank_lines_before_field=1

+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0

+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1

+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1

+org.eclipse.jdt.core.formatter.blank_lines_before_method=1

+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1

+org.eclipse.jdt.core.formatter.blank_lines_before_package=0

+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1

+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1

+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=next_line

+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=next_line

+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line

+org.eclipse.jdt.core.formatter.brace_position_for_block=next_line

+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=next_line

+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=next_line

+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=next_line

+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=next_line

+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=next_line

+org.eclipse.jdt.core.formatter.brace_position_for_switch=next_line

+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=next_line

+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=true

+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=true

+org.eclipse.jdt.core.formatter.comment.format_block_comments=true

+org.eclipse.jdt.core.formatter.comment.format_header=false

+org.eclipse.jdt.core.formatter.comment.format_html=true

+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true

+org.eclipse.jdt.core.formatter.comment.format_line_comments=true

+org.eclipse.jdt.core.formatter.comment.format_source_code=true

+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true

+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true

+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert

+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert

+org.eclipse.jdt.core.formatter.comment.line_length=120

+org.eclipse.jdt.core.formatter.compact_else_if=true

+org.eclipse.jdt.core.formatter.continuation_indentation=2

+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2

+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false

+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true

+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true

+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true

+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true

+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true

+org.eclipse.jdt.core.formatter.indent_empty_lines=false

+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true

+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true

+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true

+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false

+org.eclipse.jdt.core.formatter.indentation.size=2

+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert

+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert

+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert

+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert

+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=insert

+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert

+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert

+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=insert

+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert

+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert

+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert

+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert

+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert

+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert

+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert

+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert

+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert

+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert

+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert

+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert

+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert

+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert

+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert

+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert

+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert

+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert

+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert

+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert

+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert

+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert

+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert

+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert

+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert

+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert

+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert

+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert

+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert

+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert

+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert

+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert

+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert

+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert

+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert

+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert

+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert

+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert

+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert

+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert

+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert

+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert

+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert

+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert

+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert

+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert

+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert

+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert

+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert

+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert

+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert

+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert

+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert

+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert

+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert

+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert

+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert

+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert

+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert

+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert

+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert

+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert

+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert

+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert

+org.eclipse.jdt.core.formatter.join_lines_in_comments=true

+org.eclipse.jdt.core.formatter.join_wrapped_lines=true

+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false

+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false

+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false

+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false

+org.eclipse.jdt.core.formatter.lineSplit=120

+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false

+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false

+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0

+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1

+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true

+org.eclipse.jdt.core.formatter.tabulation.char=space

+org.eclipse.jdt.core.formatter.tabulation.size=2

+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false

+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true

+org.eclipse.jdt.core.incompatibleJDKLevel=ignore

+org.eclipse.jdt.core.incompleteClasspath=error

diff --git a/org.eclipse.emf.cdo.server.db/.settings/org.eclipse.jdt.launching.prefs b/org.eclipse.emf.cdo.server.db/.settings/org.eclipse.jdt.launching.prefs
new file mode 100644
index 0000000..4658ec1
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/.settings/org.eclipse.jdt.launching.prefs
@@ -0,0 +1,3 @@
+#Fri Sep 02 05:38:34 CEST 2011

+eclipse.preferences.version=1

+org.eclipse.jdt.launching.PREF_STRICTLY_COMPATIBLE_JRE_NOT_AVAILABLE=ignore

diff --git a/org.eclipse.emf.cdo.server.db/.settings/org.eclipse.jdt.ui.prefs b/org.eclipse.emf.cdo.server.db/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..4277817
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,120 @@
+#Thu Feb 04 09:44:24 CET 2010
+cleanup.add_default_serial_version_id=true
+cleanup.add_generated_serial_version_id=false
+cleanup.add_missing_annotations=true
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_methods=false
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=true
+cleanup.add_missing_override_annotations_interface_methods=true
+cleanup.add_serial_version_id=true
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=false
+cleanup.always_use_this_for_non_static_field_access=false
+cleanup.always_use_this_for_non_static_method_access=false
+cleanup.convert_to_enhanced_for_loop=false
+cleanup.correct_indentation=true
+cleanup.format_source_code=true
+cleanup.format_source_code_changes_only=false
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=false
+cleanup.make_private_fields_final=true
+cleanup.make_type_abstract_if_missing_method=false
+cleanup.make_variable_declarations_final=false
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=true
+cleanup.organize_imports=true
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+cleanup.qualify_static_member_accesses_with_declaring_class=false
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.remove_private_constructors=true
+cleanup.remove_trailing_whitespaces=true
+cleanup.remove_trailing_whitespaces_all=true
+cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.sort_members=false
+cleanup.sort_members_all=false
+cleanup.use_blocks=true
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_parentheses_in_expressions=true
+cleanup.use_this_for_non_static_field_access=true
+cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+cleanup.use_this_for_non_static_method_access=true
+cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+cleanup_profile=_EMFT
+cleanup_settings_version=2
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_EMFT
+formatter_settings_version=11
+org.eclipse.jdt.ui.exception.name=ex
+org.eclipse.jdt.ui.gettersetter.use.is=true
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=org.eclipse.emf.cdo;org.eclipse.emf.internal.cdo;org.eclipse.net4j;org.eclipse.internal.net4j;org.eclipse.emf;org.eclipse;com;org;javax;java;
+org.eclipse.jdt.ui.javadoc=true
+org.eclipse.jdt.ui.keywordthis=false
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.overrideannotation=true
+org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates><template autoinsert\="false" context\="gettercomment_context" deleted\="false" description\="Comment for getter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.gettercomment" name\="gettercomment"/><template autoinsert\="false" context\="settercomment_context" deleted\="false" description\="Comment for setter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.settercomment" name\="settercomment"/><template autoinsert\="false" context\="constructorcomment_context" deleted\="false" description\="Comment for created constructors" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorcomment" name\="constructorcomment"/><template autoinsert\="false" context\="filecomment_context" deleted\="false" description\="Comment for created Java files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.filecomment" name\="filecomment">/**\r\n * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.\r\n * All rights reserved. This program and the accompanying materials\r\n * are made available under the terms of the Eclipse Public License v1.0\r\n * which accompanies this distribution, and is available at\r\n * http\://www.eclipse.org/legal/epl-v10.html\r\n * \r\n * Contributors\:\r\n *    Eike Stepper - initial API and implementation\r\n */</template><template autoinsert\="false" context\="typecomment_context" deleted\="false" description\="Comment for created types" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.typecomment" name\="typecomment">/**\r\n * @author Eike Stepper\r\n */</template><template autoinsert\="false" context\="fieldcomment_context" deleted\="false" description\="Comment for fields" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment"/><template autoinsert\="false" context\="methodcomment_context" deleted\="false" description\="Comment for non-overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodcomment" name\="methodcomment"/><template autoinsert\="false" context\="overridecomment_context" deleted\="false" description\="Comment for overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.overridecomment" name\="overridecomment"/><template autoinsert\="false" context\="delegatecomment_context" deleted\="false" description\="Comment for delegate methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.delegatecomment" name\="delegatecomment"/><template autoinsert\="true" context\="newtype_context" deleted\="false" description\="Newly created files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.newtype" name\="newtype">${filecomment}\r\n${package_declaration}\r\n\r\n${typecomment}\r\n${type_declaration}</template><template autoinsert\="true" context\="classbody_context" deleted\="false" description\="Code in new class type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.classbody" name\="classbody">\r\n</template><template autoinsert\="true" context\="interfacebody_context" deleted\="false" description\="Code in new interface type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.interfacebody" name\="interfacebody">\r\n</template><template autoinsert\="true" context\="enumbody_context" deleted\="false" description\="Code in new enum type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.enumbody" name\="enumbody">\r\n</template><template autoinsert\="true" context\="annotationbody_context" deleted\="false" description\="Code in new annotation type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.annotationbody" name\="annotationbody">\r\n</template><template autoinsert\="false" context\="catchblock_context" deleted\="false" description\="Code in new catch blocks" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.catchblock" name\="catchblock">${exception_var}.printStackTrace();</template><template autoinsert\="false" context\="methodbody_context" deleted\="false" description\="Code in created method stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodbody" name\="methodbody">${body_statement}</template><template autoinsert\="false" context\="constructorbody_context" deleted\="false" description\="Code in created constructor stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorbody" name\="constructorbody">${body_statement}</template><template autoinsert\="true" context\="getterbody_context" deleted\="false" description\="Code in created getters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.getterbody" name\="getterbody">return ${field};</template><template autoinsert\="true" context\="setterbody_context" deleted\="false" description\="Code in created setters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.setterbody" name\="setterbody">${field} \= ${param};</template></templates>
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=true
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_missing_override_annotations_interface_methods=false
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=false
+sp_cleanup.always_use_this_for_non_static_method_access=false
+sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.correct_indentation=true
+sp_cleanup.format_source_code=true
+sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.make_local_variable_final=false
+sp_cleanup.make_parameters_final=false
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.organize_imports=true
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_trailing_whitespaces=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_casts=true
+sp_cleanup.remove_unnecessary_nls_tags=true
+sp_cleanup.remove_unused_imports=true
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.use_blocks=true
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_parentheses_in_expressions=true
+sp_cleanup.use_this_for_non_static_field_access=true
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+sp_cleanup.use_this_for_non_static_method_access=true
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
diff --git a/org.eclipse.emf.cdo.server.db/.settings/org.eclipse.ltk.core.refactoring.prefs b/org.eclipse.emf.cdo.server.db/.settings/org.eclipse.ltk.core.refactoring.prefs
new file mode 100644
index 0000000..864e30f
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/.settings/org.eclipse.ltk.core.refactoring.prefs
@@ -0,0 +1,3 @@
+#Thu Feb 04 09:44:24 CET 2010
+eclipse.preferences.version=1
+org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false
diff --git a/org.eclipse.emf.cdo.server.db/.settings/org.eclipse.mylyn.tasks.ui.prefs b/org.eclipse.emf.cdo.server.db/.settings/org.eclipse.mylyn.tasks.ui.prefs
new file mode 100644
index 0000000..b050639
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/.settings/org.eclipse.mylyn.tasks.ui.prefs
@@ -0,0 +1,4 @@
+#Thu Feb 04 09:44:24 CET 2010
+eclipse.preferences.version=1
+project.repository.kind=bugzilla
+project.repository.url=https\://bugs.eclipse.org/bugs
diff --git a/org.eclipse.emf.cdo.server.db/.settings/org.eclipse.mylyn.team.ui.prefs b/org.eclipse.emf.cdo.server.db/.settings/org.eclipse.mylyn.team.ui.prefs
new file mode 100644
index 0000000..2f50f36
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/.settings/org.eclipse.mylyn.team.ui.prefs
@@ -0,0 +1,3 @@
+#Thu Feb 04 09:44:24 CET 2010
+commit.comment.template=[${task.id}] ${task.description} \r\n${task.url}
+eclipse.preferences.version=1
diff --git a/org.eclipse.emf.cdo.server.db/.settings/org.eclipse.pde.api.tools.prefs b/org.eclipse.emf.cdo.server.db/.settings/org.eclipse.pde.api.tools.prefs
new file mode 100644
index 0000000..f8d0a06
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/.settings/org.eclipse.pde.api.tools.prefs
@@ -0,0 +1,94 @@
+#Thu Feb 04 09:44:24 CET 2010
+ANNOTATION_ELEMENT_TYPE_ADDED_METHOD_WITHOUT_DEFAULT_VALUE=Error
+ANNOTATION_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+ANNOTATION_ELEMENT_TYPE_REMOVED_FIELD=Error
+ANNOTATION_ELEMENT_TYPE_REMOVED_METHOD=Error
+ANNOTATION_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_API_TYPE=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_REEXPORTED_API_TYPE=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_REEXPORTED_TYPE=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_TYPE=Error
+CLASS_ELEMENT_TYPE_ADDED_METHOD=Error
+CLASS_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error
+CLASS_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+CLASS_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error
+CLASS_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+CLASS_ELEMENT_TYPE_CHANGED_NON_ABSTRACT_TO_ABSTRACT=Error
+CLASS_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error
+CLASS_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+CLASS_ELEMENT_TYPE_REMOVED_CONSTRUCTOR=Error
+CLASS_ELEMENT_TYPE_REMOVED_FIELD=Error
+CLASS_ELEMENT_TYPE_REMOVED_METHOD=Error
+CLASS_ELEMENT_TYPE_REMOVED_SUPERCLASS=Error
+CLASS_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+CLASS_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+CONSTRUCTOR_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+CONSTRUCTOR_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+CONSTRUCTOR_ELEMENT_TYPE_CHANGED_VARARGS_TO_ARRAY=Error
+CONSTRUCTOR_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+ENUM_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error
+ENUM_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+ENUM_ELEMENT_TYPE_REMOVED_ENUM_CONSTANT=Error
+ENUM_ELEMENT_TYPE_REMOVED_FIELD=Error
+ENUM_ELEMENT_TYPE_REMOVED_METHOD=Error
+ENUM_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+FIELD_ELEMENT_TYPE_ADDED_VALUE=Error
+FIELD_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+FIELD_ELEMENT_TYPE_CHANGED_FINAL_TO_NON_FINAL_STATIC_CONSTANT=Error
+FIELD_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error
+FIELD_ELEMENT_TYPE_CHANGED_NON_STATIC_TO_STATIC=Error
+FIELD_ELEMENT_TYPE_CHANGED_STATIC_TO_NON_STATIC=Error
+FIELD_ELEMENT_TYPE_CHANGED_TYPE=Error
+FIELD_ELEMENT_TYPE_CHANGED_VALUE=Error
+FIELD_ELEMENT_TYPE_REMOVED_TYPE_ARGUMENT=Error
+FIELD_ELEMENT_TYPE_REMOVED_VALUE=Error
+ILLEGAL_EXTEND=Warning
+ILLEGAL_IMPLEMENT=Warning
+ILLEGAL_INSTANTIATE=Warning
+ILLEGAL_OVERRIDE=Warning
+ILLEGAL_REFERENCE=Warning
+INTERFACE_ELEMENT_TYPE_ADDED_FIELD=Error
+INTERFACE_ELEMENT_TYPE_ADDED_METHOD=Error
+INTERFACE_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error
+INTERFACE_ELEMENT_TYPE_ADDED_SUPER_INTERFACE_WITH_METHODS=Error
+INTERFACE_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+INTERFACE_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error
+INTERFACE_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_FIELD=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_METHOD=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+INVALID_JAVADOC_TAG=Ignore
+INVALID_REFERENCE_IN_SYSTEM_LIBRARIES=Ignore
+LEAK_EXTEND=Warning
+LEAK_FIELD_DECL=Warning
+LEAK_IMPLEMENT=Warning
+LEAK_METHOD_PARAM=Warning
+LEAK_METHOD_RETURN_TYPE=Warning
+METHOD_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error
+METHOD_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+METHOD_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+METHOD_ELEMENT_TYPE_CHANGED_NON_ABSTRACT_TO_ABSTRACT=Error
+METHOD_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error
+METHOD_ELEMENT_TYPE_CHANGED_NON_STATIC_TO_STATIC=Error
+METHOD_ELEMENT_TYPE_CHANGED_STATIC_TO_NON_STATIC=Error
+METHOD_ELEMENT_TYPE_CHANGED_VARARGS_TO_ARRAY=Error
+METHOD_ELEMENT_TYPE_REMOVED_ANNOTATION_DEFAULT_VALUE=Error
+METHOD_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+TYPE_PARAMETER_ELEMENT_TYPE_ADDED_CLASS_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_ADDED_INTERFACE_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_CHANGED_CLASS_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_CHANGED_INTERFACE_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_REMOVED_CLASS_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_REMOVED_INTERFACE_BOUND=Error
+UNUSED_PROBLEM_FILTERS=Ignore
+automatically_removed_unused_problem_filters=Disabled
+eclipse.preferences.version=1
+incompatible_api_component_version=Error
+incompatible_api_component_version_include_major_without_breaking_change=Disabled
+incompatible_api_component_version_include_minor_without_api_change=Disabled
+invalid_since_tag_version=Error
+malformed_since_tag=Error
+missing_since_tag=Error
+report_api_breakage_when_major_version_incremented=Disabled
+report_resolution_errors_api_component=Warning
diff --git a/org.eclipse.emf.cdo.server.db/.settings/org.eclipse.pde.prefs b/org.eclipse.emf.cdo.server.db/.settings/org.eclipse.pde.prefs
new file mode 100644
index 0000000..c6b96bb
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/.settings/org.eclipse.pde.prefs
@@ -0,0 +1,31 @@
+#Thu Feb 04 09:44:24 CET 2010
+compilers.f.unresolved-features=1
+compilers.f.unresolved-plugins=1
+compilers.incompatible-environment=1
+compilers.p.build=1
+compilers.p.build.bin.includes=1
+compilers.p.build.java.compliance=1
+compilers.p.build.missing.output=2
+compilers.p.build.output.library=1
+compilers.p.build.source.library=1
+compilers.p.build.src.includes=1
+compilers.p.deprecated=1
+compilers.p.discouraged-class=1
+compilers.p.internal=1
+compilers.p.missing-packages=1
+compilers.p.missing-version-export-package=1
+compilers.p.missing-version-import-package=1
+compilers.p.missing-version-require-bundle=1
+compilers.p.no-required-att=0
+compilers.p.not-externalized-att=2
+compilers.p.unknown-attribute=1
+compilers.p.unknown-class=1
+compilers.p.unknown-element=1
+compilers.p.unknown-identifier=1
+compilers.p.unknown-resource=1
+compilers.p.unresolved-ex-points=0
+compilers.p.unresolved-import=0
+compilers.s.create-docs=false
+compilers.s.doc-folder=doc
+compilers.s.open-tags=1
+eclipse.preferences.version=1
diff --git a/org.eclipse.emf.cdo.server.db/META-INF/MANIFEST.MF b/org.eclipse.emf.cdo.server.db/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..b3af040
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/META-INF/MANIFEST.MF
@@ -0,0 +1,22 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: org.eclipse.emf.cdo.server.db;singleton:=true
+Bundle-Version: 4.1.0.qualifier
+Bundle-Name: %pluginName
+Bundle-Vendor: %providerName
+Bundle-Localization: plugin
+Bundle-ActivationPolicy: lazy
+Bundle-Activator: org.eclipse.emf.cdo.server.internal.db.bundle.OM$Activator
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
+Bundle-ClassPath: .
+Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.4.0,4.0.0)",
+ org.eclipse.net4j.db;bundle-version="[4.0.0,5.0.0)";visibility:=reexport,
+ org.eclipse.emf.cdo.server;bundle-version="[4.0.0,5.0.0)";visibility:=reexport
+Export-Package: org.eclipse.emf.cdo.server.db;version="4.1.0",
+ org.eclipse.emf.cdo.server.db.mapping;version="4.1.0",
+ org.eclipse.emf.cdo.server.internal.db;version="4.1.0";x-friends:="org.eclipse.emf.cdo.tests,org.eclipse.emf.cdo.tests.db",
+ org.eclipse.emf.cdo.server.internal.db.bundle;version="4.1.0";x-internal:=true,
+ org.eclipse.emf.cdo.server.internal.db.jdbc;version="4.1.0";x-friends:="org.eclipse.emf.cdo.tests,org.eclipse.emf.cdo.tests.db",
+ org.eclipse.emf.cdo.server.internal.db.mapping;version="4.1.0";x-friends:="org.eclipse.emf.cdo.tests,org.eclipse.emf.cdo.tests.db",
+ org.eclipse.emf.cdo.server.internal.db.mapping.horizontal;version="4.1.0";x-friends:="org.eclipse.emf.cdo.tests,org.eclipse.emf.cdo.tests.db",
+ org.eclipse.emf.cdo.server.internal.db.messages;version="4.1.0";x-internal:=true
diff --git a/org.eclipse.emf.cdo.server.db/about.html b/org.eclipse.emf.cdo.server.db/about.html
new file mode 100644
index 0000000..d35d5ae
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/about.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+ 
+<p>June 5, 2007</p>	
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;).  Unless otherwise 
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;).  A copy of the EPL is available 
+at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is 
+being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content.  Check the Redistributor's license that was 
+provided with the Content.  If no such license exists, contact the Redistributor.  Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
+
+</body>
+</html>
diff --git a/org.eclipse.emf.cdo.server.db/about.ini b/org.eclipse.emf.cdo.server.db/about.ini
new file mode 100644
index 0000000..32006ae
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/about.ini
@@ -0,0 +1,15 @@
+# about.ini
+# contains information about a feature
+# java.io.Properties file (ISO 8859-1 with "\" escapes)
+# "%key" are externalized strings defined in about.properties
+# This file does not need to be translated.
+
+# Property "aboutText" contains blurb for "About" dialog (translated)
+aboutText=%featureText 
+
+# Property "featureImage" contains path to feature image (32x32)
+featureImage=modeling32.png
+
+# Property "appName" contains name of the application (translated)
+appName=%featureName
+
diff --git a/org.eclipse.emf.cdo.server.db/about.mappings b/org.eclipse.emf.cdo.server.db/about.mappings
new file mode 100644
index 0000000..bddaab4
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/about.mappings
@@ -0,0 +1,6 @@
+# about.mappings
+# contains fill-ins for about.properties
+# java.io.Properties file (ISO 8859-1 with "\" escapes)
+# This file does not need to be translated.
+
+0=@build@
\ No newline at end of file
diff --git a/org.eclipse.emf.cdo.server.db/about.properties b/org.eclipse.emf.cdo.server.db/about.properties
new file mode 100644
index 0000000..949ccad
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/about.properties
@@ -0,0 +1,31 @@
+# Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#    Eike Stepper - initial API and implementation
+
+# NLS_MESSAGEFORMAT_VAR
+
+# ==============================================================================
+# Do not change the properties between this line and the last line containing:
+# %%% END OF TRANSLATED PROPERTIES %%%
+# Instead, either redefine an existing property, or create a new property,
+# append it to the end of the file, and change the code to use the new name.
+# ==============================================================================
+
+featureName = CDO Model Repository Server DB
+featureText = CDO Model Repository Server DB\n\
+Version: {featureVersion}\n\
+Build id: {0}\n\
+\n\
+Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others. All rights reserved.\n\
+\n\
+Visit http://www.eclipse.org/cdo
+
+# ==============================================================================
+# %%% END OF TRANSLATED PROPERTIES %%%
+# The above properties have been shipped for translation.
+# ==============================================================================
diff --git a/org.eclipse.emf.cdo.server.db/build.properties b/org.eclipse.emf.cdo.server.db/build.properties
new file mode 100644
index 0000000..7962001
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/build.properties
@@ -0,0 +1,29 @@
+# Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#    Eike Stepper - initial API and implementation
+
+# NLS_MESSAGEFORMAT_VAR
+
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .,\
+               .options,\
+               about.html,\
+               copyright.txt,\
+               plugin.xml,\
+               schema/,\
+               plugin.properties,\
+               about.ini,\
+               about.mappings,\
+               about.properties,\
+               modeling32.png
+src.includes = about.html,\
+               copyright.txt
+
+org.eclipse.emf.cdo.releng.javadoc.project = org.eclipse.emf.cdo.doc
diff --git a/org.eclipse.emf.cdo.server.db/copyright.txt b/org.eclipse.emf.cdo.server.db/copyright.txt
new file mode 100644
index 0000000..e921242
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/copyright.txt
@@ -0,0 +1,8 @@
+Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+All rights reserved. This program and the accompanying materials
+are made available under the terms of the Eclipse Public License v1.0
+which accompanies this distribution, and is available at
+http://www.eclipse.org/legal/epl-v10.html
+
+Contributors:
+   Eike Stepper - initial API and implementation
\ No newline at end of file
diff --git a/org.eclipse.emf.cdo.server.db/modeling32.png b/org.eclipse.emf.cdo.server.db/modeling32.png
new file mode 100644
index 0000000..6b08de2
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/modeling32.png
Binary files differ
diff --git a/org.eclipse.emf.cdo.server.db/plugin.properties b/org.eclipse.emf.cdo.server.db/plugin.properties
new file mode 100644
index 0000000..ade0c88
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/plugin.properties
@@ -0,0 +1,13 @@
+# Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#    Eike Stepper - initial API and implementation
+
+pluginName = CDO Model Repository Server DB
+providerName = Eclipse Modeling Project
+
+extension-point.name = CDO Mapping Strategies
\ No newline at end of file
diff --git a/org.eclipse.emf.cdo.server.db/plugin.xml b/org.eclipse.emf.cdo.server.db/plugin.xml
new file mode 100644
index 0000000..6abb1a8
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/plugin.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<!--
+	Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+	All rights reserved. This program and the accompanying materials
+	are made available under the terms of the Eclipse Public License v1.0
+	which accompanies this distribution, and is available at
+	http://www.eclipse.org/legal/epl-v10.html
+	
+	Contributors:
+	  Eike Stepper - initial API and implementation
+-->
+
+<plugin>
+
+   <extension-point id="mappingStrategies" name="%extension-point.name" schema="schema/mappingStrategies.exsd"/>
+   
+   <extension
+         point="org.eclipse.net4j.util.factories">
+      <factory
+            class="org.eclipse.emf.cdo.server.internal.db.DBBrowserPage$Factory"
+            productGroup="org.eclipse.emf.cdo.server.browserPages"
+            type="db">
+      </factory>
+   </extension>
+
+   <extension
+         point="org.eclipse.emf.cdo.server.storeFactories">
+      <storeFactory
+            class="org.eclipse.emf.cdo.server.internal.db.DBStoreFactory"
+            storeType="db">
+      </storeFactory>
+   </extension>
+
+   <extension
+         point="org.eclipse.emf.cdo.server.db.mappingStrategies">
+      <mappingStrategy
+            class="org.eclipse.emf.cdo.server.internal.db.mapping.horizontal.HorizontalMappingStrategy"
+            type="horizontal"/>
+      <mappingStrategy
+            class="org.eclipse.emf.cdo.server.internal.db.mapping.horizontal.HorizontalNonAuditMappingStrategy"
+            type="horizontalNonAuditing"/>
+      <mappingStrategy
+            class="org.eclipse.emf.cdo.server.internal.db.mapping.horizontal.HorizontalAuditMappingStrategy"
+            type="horizontalAuditing"/>
+      <mappingStrategy
+            class="org.eclipse.emf.cdo.server.internal.db.mapping.horizontal.HorizontalBranchingMappingStrategy"
+            type="horizontalBranching"/>
+      <mappingStrategy
+            class="org.eclipse.emf.cdo.server.internal.db.mapping.horizontal.HorizontalAuditMappingStrategyWithRanges"
+            type="horizontalAuditingWithRanges"/>
+      <mappingStrategy
+            class="org.eclipse.emf.cdo.server.internal.db.mapping.horizontal.HorizontalBranchingMappingStrategyWithRanges"
+            type="horizontalBranchingWithRanges"/>
+   </extension>
+   
+</plugin>
diff --git a/org.eclipse.emf.cdo.server.db/schema/mappingStrategies.exsd b/org.eclipse.emf.cdo.server.db/schema/mappingStrategies.exsd
new file mode 100644
index 0000000..c708d55
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/schema/mappingStrategies.exsd
@@ -0,0 +1,113 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.emf.cdo.server.db">
+<annotation>
+      <appInfo>
+         <meta.schema plugin="org.eclipse.emf.cdo.server.db" id="mappingStrategies" name="CDO Mapping Strategies"/>
+      </appInfo>
+      <documentation>
+         [Enter description of this extension point.]
+      </documentation>
+   </annotation>
+
+   <element name="extension">
+      <complexType>
+         <sequence>
+            <element ref="mappingStrategy" minOccurs="1" maxOccurs="unbounded"/>
+         </sequence>
+         <attribute name="point" type="string" use="required">
+            <annotation>
+               <documentation>
+
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="name" type="string">
+            <annotation>
+               <documentation>
+
+               </documentation>
+               <appInfo>
+                  <meta.attribute translatable="true"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="mappingStrategy">
+      <complexType>
+         <attribute name="type" type="string" use="required">
+            <annotation>
+               <documentation>
+
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="class" type="string" use="required">
+            <annotation>
+               <documentation>
+
+               </documentation>
+               <appInfo>
+                  <meta.attribute kind="java" basedOn=":org.eclipse.emf.cdo.server.db.IMappingStrategy"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="since"/>
+      </appInfo>
+      <documentation>
+         [Enter the first release in which this extension point appears.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="examples"/>
+      </appInfo>
+      <documentation>
+         [Enter extension point usage example here.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="apiInfo"/>
+      </appInfo>
+      <documentation>
+         [Enter API information here.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="implementation"/>
+      </appInfo>
+      <documentation>
+         [Enter information about supplied implementation of this extension point.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appinfo>
+         <meta.section type="copyright"/>
+      </appinfo>
+      <documentation>
+         Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.&lt;br&gt;
+All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at &lt;a href=&quot;http://www.eclipse.org/legal/epl-v10.html&quot;&gt;http://www.eclipse.org/legal/epl-v10.html&lt;/a&gt;
+      </documentation>
+   </annotation>
+
+</schema>
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/CDODBUtil.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/CDODBUtil.java
new file mode 100644
index 0000000..b5cb29a
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/CDODBUtil.java
@@ -0,0 +1,202 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - 271444: [DB] Multiple refactorings
+ *    Stefan Winkler - 249610: [DB] Support external references (Implementation)
+ */
+package org.eclipse.emf.cdo.server.db;
+
+import org.eclipse.emf.cdo.server.db.mapping.IMappingStrategy;
+import org.eclipse.emf.cdo.server.internal.db.DBBrowserPage;
+import org.eclipse.emf.cdo.server.internal.db.DBStore;
+import org.eclipse.emf.cdo.server.internal.db.SmartPreparedStatementCache;
+import org.eclipse.emf.cdo.server.internal.db.bundle.OM;
+import org.eclipse.emf.cdo.server.internal.db.mapping.horizontal.HorizontalAuditMappingStrategy;
+import org.eclipse.emf.cdo.server.internal.db.mapping.horizontal.HorizontalAuditMappingStrategyWithRanges;
+import org.eclipse.emf.cdo.server.internal.db.mapping.horizontal.HorizontalBranchingMappingStrategy;
+import org.eclipse.emf.cdo.server.internal.db.mapping.horizontal.HorizontalBranchingMappingStrategyWithRanges;
+import org.eclipse.emf.cdo.server.internal.db.mapping.horizontal.HorizontalMappingStrategy;
+import org.eclipse.emf.cdo.server.internal.db.mapping.horizontal.HorizontalNonAuditMappingStrategy;
+
+import org.eclipse.net4j.db.IDBAdapter;
+import org.eclipse.net4j.db.IDBConnectionProvider;
+import org.eclipse.net4j.util.ObjectUtil;
+import org.eclipse.net4j.util.WrappedException;
+import org.eclipse.net4j.util.container.IManagedContainer;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.Platform;
+
+/**
+ * @author Eike Stepper
+ */
+public final class CDODBUtil
+{
+  /**
+   * @since 2.0
+   */
+  public static final int DEFAULT_STATEMENT_CACHE_CAPACITY = 200;
+
+  /**
+   * @since 2.0
+   */
+  public static final String EXT_POINT_MAPPING_STRATEGIES = "mappingStrategies"; //$NON-NLS-1$
+
+  /**
+   * @since 4.1
+   */
+  public static final String PROP_WITH_RANGES = "withRanges";
+
+  /**
+   * @since 4.1
+   */
+  public static final String PROP_COPY_ON_BRANCH = "copyOnBranch";
+
+  private CDODBUtil()
+  {
+  }
+
+  /**
+   * @since 4.0
+   */
+  public static void prepareContainer(IManagedContainer container)
+  {
+    container.registerFactory(new DBBrowserPage.Factory());
+  }
+
+  /**
+   * @since 2.0
+   */
+  public static IDBStore createStore(IMappingStrategy mappingStrategy, IDBAdapter dbAdapter,
+      IDBConnectionProvider dbConnectionProvider)
+  {
+    DBStore store = new DBStore();
+    store.setMappingStrategy(mappingStrategy);
+    store.setDBAdapter(dbAdapter);
+    store.setDbConnectionProvider(dbConnectionProvider);
+    return store;
+  }
+
+  /**
+   * @since 2.0
+   */
+  public static IMappingStrategy createHorizontalMappingStrategy(boolean auditing)
+  {
+    return createHorizontalMappingStrategy(auditing, false, false);
+  }
+
+  /**
+   * @since 3.0
+   */
+  public static IMappingStrategy createHorizontalMappingStrategy(boolean auditing, boolean branching)
+  {
+    return createHorizontalMappingStrategy(auditing, branching, false);
+  }
+
+  /**
+   * @since 4.1
+   */
+  public static IMappingStrategy createHorizontalMappingStrategy(boolean auditing, boolean branching, boolean withRanges)
+  {
+    if (branching)
+    {
+      if (auditing)
+      {
+        if (withRanges)
+        {
+          return new HorizontalBranchingMappingStrategyWithRanges();
+        }
+
+        return new HorizontalBranchingMappingStrategy();
+      }
+
+      throw new IllegalArgumentException("Misconfiguration: Branching requires Auditing!");
+    }
+
+    if (auditing)
+    {
+      if (withRanges)
+      {
+        return new HorizontalAuditMappingStrategyWithRanges();
+      }
+
+      return new HorizontalAuditMappingStrategy();
+    }
+
+    return new HorizontalNonAuditMappingStrategy();
+  }
+
+  /**
+   * Creates a horizontal {@link IMappingStrategy mapping strategy} that supports all valid combinations of auditing and
+   * branching.
+   * 
+   * @since 4.1
+   */
+  public static IMappingStrategy createHorizontalMappingStrategy()
+  {
+    return new HorizontalMappingStrategy();
+  }
+
+  /**
+   * Can only be used when Eclipse is running. In standalone scenarios create the mapping strategy instance by directly
+   * calling the constructor of the mapping strategy class.
+   * 
+   * @see #createHorizontalMappingStrategy(boolean)
+   * @see #createHorizontalMappingStrategy(boolean, boolean)
+   * @since 2.0
+   */
+  public static IMappingStrategy createMappingStrategy(String type)
+  {
+    IExtensionRegistry registry = Platform.getExtensionRegistry();
+    IConfigurationElement[] elements = registry.getConfigurationElementsFor(OM.BUNDLE_ID, EXT_POINT_MAPPING_STRATEGIES);
+    for (final IConfigurationElement element : elements)
+    {
+      if ("mappingStrategy".equals(element.getName())) //$NON-NLS-1$
+      {
+        String typeAttr = element.getAttribute("type"); //$NON-NLS-1$
+        if (ObjectUtil.equals(typeAttr, type))
+        {
+          try
+          {
+            return (IMappingStrategy)element.createExecutableExtension("class"); //$NON-NLS-1$
+          }
+          catch (CoreException ex)
+          {
+            throw WrappedException.wrap(ex);
+          }
+        }
+      }
+    }
+
+    return null;
+  }
+
+  /**
+   * Creates a prepared statement cache with the {@link CDODBUtil#DEFAULT_STATEMENT_CACHE_CAPACITY default capacity}.
+   * 
+   * @since 2.0
+   * @see CDODBUtil#createStatementCache(int)
+   */
+  public static IPreparedStatementCache createStatementCache()
+  {
+    return createStatementCache(DEFAULT_STATEMENT_CACHE_CAPACITY);
+  }
+
+  /**
+   * Creates a prepared statement cache with the given capacity.
+   * 
+   * @since 2.0
+   */
+  public static IPreparedStatementCache createStatementCache(int capacity)
+  {
+    return new SmartPreparedStatementCache(capacity);
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/IDBStore.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/IDBStore.java
new file mode 100644
index 0000000..c1c6d23
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/IDBStore.java
@@ -0,0 +1,70 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - 271444: [DB] Multiple refactorings
+ *    Stefan Winkler - 249610: [DB] Support external references (Implementation)
+ */
+package org.eclipse.emf.cdo.server.db;
+
+import org.eclipse.emf.cdo.server.ISession;
+import org.eclipse.emf.cdo.server.IStore;
+import org.eclipse.emf.cdo.server.IStore.CanHandleClientAssignedIDs;
+import org.eclipse.emf.cdo.server.ITransaction;
+import org.eclipse.emf.cdo.server.db.mapping.IMappingStrategy;
+
+import org.eclipse.net4j.db.IDBAdapter;
+import org.eclipse.net4j.db.IDBConnectionProvider;
+import org.eclipse.net4j.db.ddl.IDBSchema;
+
+/**
+ * @author Eike Stepper
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface IDBStore extends IStore, IDBConnectionProvider, CanHandleClientAssignedIDs
+{
+  /**
+   * @since 2.0
+   */
+  public IMappingStrategy getMappingStrategy();
+
+  /**
+   * @since 4.0
+   */
+  public IIDHandler getIDHandler();
+
+  public IDBAdapter getDBAdapter();
+
+  public IDBSchema getDBSchema();
+
+  /**
+   * Get the meta data manager associated with this DBStore.
+   * 
+   * @since 2.0
+   */
+  public IMetaDataManager getMetaDataManager();
+
+  /**
+   * @since 2.0
+   */
+  public IDBStoreAccessor getReader(ISession session);
+
+  /**
+   * @since 2.0
+   */
+  public IDBStoreAccessor getWriter(ITransaction transaction);
+
+  /**
+   * @since 4.0
+   */
+  public interface Props
+  {
+    public static final String CONNECTION_KEEPALIVE_PERIOD = "connectionKeepAlivePeriod"; //$NON-NLS-1$
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/IDBStoreAccessor.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/IDBStoreAccessor.java
new file mode 100644
index 0000000..2d50794
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/IDBStoreAccessor.java
@@ -0,0 +1,32 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server.db;
+
+import org.eclipse.emf.cdo.server.IStoreAccessor;
+
+import java.sql.Connection;
+
+/**
+ * @author Eike Stepper
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface IDBStoreAccessor extends IStoreAccessor.Raw
+{
+  public IDBStore getStore();
+
+  public Connection getConnection();
+
+  /**
+   * @since 2.0
+   */
+  public IPreparedStatementCache getStatementCache();
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/IDBStoreChunkReader.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/IDBStoreChunkReader.java
new file mode 100644
index 0000000..67f9bea
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/IDBStoreChunkReader.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server.db;
+
+import org.eclipse.emf.cdo.server.IStoreChunkReader;
+
+/**
+ * @author Eike Stepper
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface IDBStoreChunkReader extends IStoreChunkReader
+{
+  /**
+   * @since 2.0
+   */
+  public IDBStoreAccessor getAccessor();
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/IIDHandler.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/IIDHandler.java
new file mode 100644
index 0000000..0bbee5d
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/IIDHandler.java
@@ -0,0 +1,89 @@
+/**

+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ * 

+ * Contributors:

+ *    Eike Stepper - initial API and implementation

+ */

+package org.eclipse.emf.cdo.server.db;

+

+import org.eclipse.emf.cdo.common.id.CDOID;

+import org.eclipse.emf.cdo.common.id.CDOID.ObjectType;

+import org.eclipse.emf.cdo.common.protocol.CDODataInput;

+import org.eclipse.emf.cdo.common.protocol.CDODataOutput;

+import org.eclipse.emf.cdo.common.revision.CDORevision;

+import org.eclipse.emf.cdo.server.db.mapping.ITypeMapping;

+

+import org.eclipse.net4j.db.DBType;

+import org.eclipse.net4j.util.om.monitor.OMMonitor;

+

+import java.io.IOException;

+import java.sql.Connection;

+import java.sql.PreparedStatement;

+import java.sql.ResultSet;

+import java.sql.SQLException;

+import java.util.Comparator;

+import java.util.Set;

+

+/**

+ * @author Eike Stepper

+ * @since 4.0

+ * @noextend This interface is not intended to be extended by clients.

+ * @noimplement This interface is not intended to be implemented by clients.

+ */

+public interface IIDHandler extends Comparator<CDOID>

+{

+  public IDBStore getStore();

+

+  public DBType getDBType();

+

+  public Set<ObjectType> getObjectIDTypes();

+

+  public ITypeMapping getObjectTypeMapping();

+

+  public CDOID createCDOID(String val);

+

+  public boolean isLocalCDOID(CDOID id);

+

+  public CDOID getLastObjectID();

+

+  public void setLastObjectID(CDOID lastObjectID);

+

+  /**

+   * @since 4.1

+   */

+  public void adjustLastObjectID(CDOID maxID);

+

+  public CDOID getNextLocalObjectID();

+

+  public void setNextLocalObjectID(CDOID nextLocalObjectID);

+

+  public CDOID getNextCDOID(CDORevision revision);

+

+  public void appendCDOID(StringBuilder builder, CDOID id);

+

+  public void setCDOID(PreparedStatement stmt, int column, CDOID id) throws SQLException;

+

+  public void setCDOID(PreparedStatement stmt, int column, CDOID id, long commitTime) throws SQLException;

+

+  public CDOID getCDOID(ResultSet resultSet, int column) throws SQLException;

+

+  public CDOID getCDOID(ResultSet resultSet, String name) throws SQLException;

+

+  public CDOID getMinCDOID();

+

+  public CDOID getMaxCDOID();

+

+  public CDOID mapURI(IDBStoreAccessor accessor, String uri, long commitTime);

+

+  public String unmapURI(IDBStoreAccessor accessor, CDOID id);

+

+  public void rawExport(Connection connection, CDODataOutput out, long fromCommitTime, long toCommitTime)

+      throws IOException;

+

+  public void rawImport(Connection connection, CDODataInput in, long fromCommitTime, long toCommitTime, OMMonitor fork)

+      throws IOException;

+}

diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/IMetaDataManager.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/IMetaDataManager.java
new file mode 100644
index 0000000..972d735
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/IMetaDataManager.java
@@ -0,0 +1,110 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - bug 271444: [DB] Multiple refactorings
+ *    Kai Schlamp - bug 282976: [DB] Influence Mappings through EAnnotations
+ *    Stefan Winkler - bug 282976: [DB] Influence Mappings through EAnnotations
+ */
+package org.eclipse.emf.cdo.server.db;
+
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.protocol.CDODataInput;
+import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit;
+
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+
+import org.eclipse.emf.ecore.EModelElement;
+import org.eclipse.emf.ecore.EPackage;
+
+import java.io.IOException;
+import java.sql.Connection;
+import java.util.Collection;
+
+/**
+ * @author Eike Stepper
+ * @since 2.0
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface IMetaDataManager
+{
+  /**
+   * Returns the meta ID of the given {@link EModelElement}. <code> getMetaID(getMetaInstance(x))</code> yields
+   * <code>x</code>
+   * 
+   * @param modelElement
+   *          the element
+   * @return the corresponding ID
+   * @since 4.0
+   */
+  public CDOID getMetaID(EModelElement modelElement, long commitTime);
+
+  /**
+   * Returns the {@link EModelElement} referred to by the given ID. <code> getMetaInstance(getMetaID(m))</code> yields
+   * <code>m</code>
+   * 
+   * @since 4.0
+   */
+  public EModelElement getMetaInstance(CDOID id);
+
+  /**
+   * Loads a package unit from the database.
+   * 
+   * @param connection
+   *          the DB connection to read from.
+   * @param packageUnit
+   *          the package unit to load.
+   * @return the loaded package unit.
+   * @since 2.0
+   */
+  public EPackage[] loadPackageUnit(Connection connection, InternalCDOPackageUnit packageUnit);
+
+  /**
+   * @since 4.0
+   */
+  public void clearMetaIDMappings();
+
+  /**
+   * Reads information about package units present in the database.
+   * 
+   * @param connection
+   *          the DB connection to read from.
+   * @return a collection of package unit information records which can be passed to
+   *         {@link IMetaDataManager#loadPackageUnit(Connection, InternalCDOPackageUnit)} in order to read the EPackage.
+   * @since 2.0
+   */
+  public Collection<InternalCDOPackageUnit> readPackageUnits(Connection connection);
+
+  /**
+   * Write package units to the database.
+   * 
+   * @param connection
+   *          the DB connection to write to.
+   * @param packageUnits
+   *          the package units to write.
+   * @param monitor
+   *          the monitor to indicate progress.
+   * @since 2.0
+   */
+  public void writePackageUnits(Connection connection, InternalCDOPackageUnit[] packageUnits, OMMonitor monitor);
+
+  /**
+   * @since 3.0
+   */
+  public void rawExport(Connection connection, CDODataOutput out, long fromCommitTime, long toCommitTime)
+      throws IOException;
+
+  /**
+   * @since 4.0
+   */
+  public Collection<InternalCDOPackageUnit> rawImport(Connection connection, CDODataInput in, long fromCommitTime,
+      long toCommitTime, OMMonitor monitor) throws IOException;
+
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/IPreparedStatementCache.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/IPreparedStatementCache.java
new file mode 100644
index 0000000..4c81edc
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/IPreparedStatementCache.java
@@ -0,0 +1,52 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - 271444: [DB] Multiple refactorings bug 271444
+ */
+package org.eclipse.emf.cdo.server.db;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+
+/**
+ * @author Stefan Winkler
+ * @since 2.0
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface IPreparedStatementCache
+{
+  public void setConnection(Connection connection);
+
+  public PreparedStatement getPreparedStatement(String sql, ReuseProbability reuseProbability);
+
+  public void releasePreparedStatement(PreparedStatement ps);
+
+  /**
+   * An enum for the degree of probability to which a prepared statement is reused later on. This is used for managing
+   * the cache of prepared statements so that statements which are more likely reused are kept in the cache longer. Rule
+   * of thumb:
+   * <ul>
+   * <li>For global statements which are used regularly (such as lookup object in cdo_objects) use
+   * {@link ReuseProbability#MAX MAX}.
+   * <li>For constant object-specific statements which are used regularly use {@link ReuseProbability#HIGH HIGH}.
+   * <li>For object-specific statements which are assembled from constants which are used regularly use
+   * {@link ReuseProbability#MEDIUM MEDIUM}.
+   * <li>For all other dynamic statements, like queries, use {@link ReuseProbability#LOW LOW}
+   * </ul>
+   * 
+   * @author Stefan Winkler
+   * @since 2.0
+   * @noextend This interface is not intended to be extended by clients.
+   */
+  public static enum ReuseProbability
+  {
+    MAX, HIGH, MEDIUM, LOW;
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/AbstractTypeMapping.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/AbstractTypeMapping.java
new file mode 100644
index 0000000..745e96e
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/AbstractTypeMapping.java
@@ -0,0 +1,287 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - bug 271444: [DB] Multiple refactorings
+ *    Stefan Winkler - bug 275303: [DB] DBStore does not handle BIG_INTEGER and BIG_DECIMAL
+ *    Kai Schlamp - bug 282976: [DB] Influence Mappings through EAnnotations
+ *    Stefan Winkler - bug 282976: [DB] Influence Mappings through EAnnotations
+ *    Stefan Winkler - bug 285270: [DB] Support XSD based models
+ *    Stefan Winkler - Bug 285426: [DB] Implement user-defined typeMapping support
+ */
+package org.eclipse.emf.cdo.server.db.mapping;
+
+import org.eclipse.emf.cdo.common.revision.CDORevisionData;
+import org.eclipse.emf.cdo.server.internal.db.DBAnnotation;
+import org.eclipse.emf.cdo.server.internal.db.MetaDataManager;
+import org.eclipse.emf.cdo.server.internal.db.bundle.OM;
+import org.eclipse.emf.cdo.server.internal.db.mapping.TypeMappingRegistry;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+
+import org.eclipse.net4j.db.DBType;
+import org.eclipse.net4j.db.ddl.IDBField;
+import org.eclipse.net4j.db.ddl.IDBTable;
+import org.eclipse.net4j.util.container.IManagedContainer;
+import org.eclipse.net4j.util.om.trace.ContextTracer;
+
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+/**
+ * This is a default implementation for the {@link ITypeMapping} interface which provides default behavor for all common
+ * types. Implementors should provide a constructor which the factory (see below) can use and implement
+ * {@link #getResultSetValue(ResultSet)}. If needed, {@link #doSetValue(PreparedStatement, int, Object)} can also be
+ * overridden as a counterpart to {@link #getResultSetValue(ResultSet)}. Finally, an implementor should also implement a
+ * suitable factory for the {@link TypeMappingRegistry} and register it either manually using
+ * {@link IManagedContainer#registerFactory(org.eclipse.net4j.util.factory.IFactory)} or using the Net4j Extension Point
+ * <code>factories</code>.
+ * 
+ * @author Eike Stepper
+ * @author Stefan Winkler
+ * @since 4.0
+ */
+public abstract class AbstractTypeMapping implements ITypeMapping
+{
+  private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG, AbstractTypeMapping.class);
+
+  private IMappingStrategy mappingStrategy;
+
+  private EStructuralFeature feature;
+
+  private IDBField field;
+
+  private DBType dbType;
+
+  /**
+   * Create a new type mapping
+   */
+  public AbstractTypeMapping()
+  {
+    super();
+  }
+
+  public final void setMappingStrategy(IMappingStrategy mappingStrategy)
+  {
+    this.mappingStrategy = mappingStrategy;
+  }
+
+  public final IMappingStrategy getMappingStrategy()
+  {
+    return mappingStrategy;
+  }
+
+  public final void setFeature(EStructuralFeature feature)
+  {
+    this.feature = feature;
+  }
+
+  public final EStructuralFeature getFeature()
+  {
+    return feature;
+  }
+
+  public final void setValueFromRevision(PreparedStatement stmt, int index, InternalCDORevision revision)
+      throws SQLException
+  {
+    setValue(stmt, index, getRevisionValue(revision));
+  }
+
+  public final void setDefaultValue(PreparedStatement stmt, int index) throws SQLException
+  {
+    setValue(stmt, index, getDefaultValue());
+  }
+
+  public final void setValue(PreparedStatement stmt, int index, Object value) throws SQLException
+  {
+    if (value == CDORevisionData.NIL)
+    {
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("TypeMapping for {0}: converting Revision.NIL to DB-null", feature.getName()); //$NON-NLS-1$
+      }
+
+      stmt.setNull(index, getSqlType());
+    }
+    else if (value == null)
+    {
+      if (feature.isMany() || getDefaultValue() == null)
+      {
+        if (TRACER.isEnabled())
+        {
+          TRACER.format("TypeMapping for {0}: writing Revision.null as DB.null", feature.getName()); //$NON-NLS-1$
+        }
+
+        stmt.setNull(index, getSqlType());
+      }
+      else
+      {
+        if (TRACER.isEnabled())
+        {
+          TRACER.format("TypeMapping for {0}: converting Revision.null to default value", feature.getName()); //$NON-NLS-1$
+        }
+
+        setDefaultValue(stmt, index);
+      }
+    }
+    else
+    {
+      doSetValue(stmt, index, value);
+    }
+  }
+
+  public final void createDBField(IDBTable table)
+  {
+    createDBField(table, mappingStrategy.getFieldName(feature));
+  }
+
+  public final void createDBField(IDBTable table, String fieldName)
+  {
+    DBType fieldType = getDBType();
+    int fieldLength = getDBLength(fieldType);
+    field = table.addField(fieldName, fieldType, fieldLength);
+  }
+
+  public final void setDBField(IDBTable table, String fieldName)
+  {
+    field = table.getField(fieldName);
+  }
+
+  public final IDBField getField()
+  {
+    return field;
+  }
+
+  public final void readValueToRevision(ResultSet resultSet, InternalCDORevision revision) throws SQLException
+  {
+    Object value = readValue(resultSet);
+    revision.setValue(getFeature(), value);
+  }
+
+  public final Object readValue(ResultSet resultSet) throws SQLException
+  {
+    Object value = getResultSetValue(resultSet);
+    if (resultSet.wasNull())
+    {
+      if (feature.isMany())
+      {
+        if (TRACER.isEnabled())
+        {
+          TRACER.format("TypeMapping for {0}: read db.null - setting Revision.null", feature.getName()); //$NON-NLS-1$
+        }
+
+        value = null;
+      }
+      else
+      {
+        if (getDefaultValue() == null)
+        {
+          if (TRACER.isEnabled())
+          {
+            TRACER.format(
+                "TypeMapping for {0}: read db.null - setting Revision.null, because of default", feature.getName()); //$NON-NLS-1$
+          }
+
+          value = null;
+        }
+        else
+        {
+          if (TRACER.isEnabled())
+          {
+            TRACER.format("TypeMapping for {0}: read db.null - setting Revision.NIL", feature.getName()); //$NON-NLS-1$
+          }
+
+          value = CDORevisionData.NIL;
+        }
+      }
+    }
+
+    return value;
+  }
+
+  protected Object getDefaultValue()
+  {
+    return feature.getDefaultValue();
+  }
+
+  protected final Object getRevisionValue(InternalCDORevision revision)
+  {
+    return revision.getValue(getFeature());
+  }
+
+  /**
+   * Implementors could override this method to convert a given value to the database representation and set it to the
+   * prepared statement.
+   * 
+   * @param stmt
+   *          the {@link PreparedStatement} which is used for DB access
+   * @param index
+   *          the parameter index in the statement which should be set
+   * @param value
+   *          the value of the feature which should be written into the DB
+   */
+  protected void doSetValue(PreparedStatement stmt, int index, Object value) throws SQLException
+  {
+    stmt.setObject(index, value, getSqlType());
+  }
+
+  /**
+   * Returns the SQL type of this TypeMapping. The default implementation considers the type map held by the
+   * {@link MetaDataManager meta-data manager}. Subclasses may override.
+   * 
+   * @return The sql type of this TypeMapping.
+   */
+  protected int getSqlType()
+  {
+    return getDBType().getCode();
+  }
+
+  public final void setDBType(DBType dbType)
+  {
+    this.dbType = dbType;
+  }
+
+  public DBType getDBType()
+  {
+    return dbType;
+  }
+
+  protected int getDBLength(DBType type)
+  {
+    String value = DBAnnotation.COLUMN_LENGTH.getValue(feature);
+    if (value != null)
+    {
+      try
+      {
+        return Integer.parseInt(value);
+      }
+      catch (NumberFormatException e)
+      {
+        OM.LOG.error("Illegal columnLength annotation of feature " + feature.getName());
+      }
+    }
+
+    // TODO: implement DBAdapter.getDBLength
+    // mappingStrategy.getStore().getDBAdapter().getDBLength(type);
+    // which should then return the correct default field length for the db type
+    return type == DBType.VARCHAR ? 32672 : IDBField.DEFAULT;
+  }
+
+  /**
+   * Subclasses should implement this method to read the value from the result set. Typical implementations should look
+   * similar to this one: <code>resultSet.getString(getField().getName())</code>
+   * 
+   * @param resultSet
+   *          the result set to read from
+   * @return the result value read (this has to be compatible with the {@link #feature}.
+   */
+  protected abstract Object getResultSetValue(ResultSet resultSet) throws SQLException;
+
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/AbstractTypeMappingFactory.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/AbstractTypeMappingFactory.java
new file mode 100644
index 0000000..4170dbf
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/AbstractTypeMappingFactory.java
@@ -0,0 +1,43 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server.db.mapping;
+
+import org.eclipse.emf.cdo.server.db.mapping.ITypeMapping.Descriptor;
+
+import org.eclipse.net4j.util.factory.Factory;
+import org.eclipse.net4j.util.factory.ProductCreationException;
+
+/**
+ * Abstract implementation for {@link ITypeMapping.Factory}. Implementors should implement their custom
+ * {@link #create(String)} method and construct the factory using their custom descriptor. Subclasses must have a
+ * default constructor!
+ * 
+ * @author Stefan Winkler
+ * @since 4.0
+ */
+public abstract class AbstractTypeMappingFactory extends Factory implements
+    org.eclipse.emf.cdo.server.db.mapping.ITypeMapping.Factory
+{
+  private ITypeMapping.Descriptor descriptor;
+
+  public AbstractTypeMappingFactory(Descriptor descriptor)
+  {
+    super(PRODUCT_GROUP, descriptor.getFactoryType());
+    this.descriptor = descriptor;
+  }
+
+  public abstract ITypeMapping create(String description) throws ProductCreationException;
+
+  public final Descriptor getDescriptor()
+  {
+    return descriptor;
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/IClassMapping.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/IClassMapping.java
new file mode 100644
index 0000000..9775d42
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/IClassMapping.java
@@ -0,0 +1,201 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - 271444: [DB] Multiple refactorings bug 271444
+ */
+package org.eclipse.emf.cdo.server.db.mapping;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionHandler;
+import org.eclipse.emf.cdo.server.IStoreAccessor;
+import org.eclipse.emf.cdo.server.IStoreAccessor.QueryXRefsContext;
+import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
+import org.eclipse.emf.cdo.spi.common.commit.CDOChangeSetSegment;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+
+import org.eclipse.net4j.db.ddl.IDBTable;
+import org.eclipse.net4j.util.ImplementationError;
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+import java.sql.PreparedStatement;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Basic interface for class mappings.
+ * 
+ * @author Eike Stepper
+ * @author Stefan Winkler
+ * @since 2.0
+ */
+public interface IClassMapping
+{
+  /**
+   * @since 3.0
+   */
+  public EClass getEClass();
+
+  /**
+   * Returns all DB tables which are used by this class and all its contained features.
+   * 
+   * @return a collection of all tables of this class and all its contained features.
+   * @since 3.0
+   */
+  public List<IDBTable> getDBTables();
+
+  /**
+   * Get the mapping of the many-valued feature.
+   * 
+   * @param feature
+   *          the feature for which the mapping should be returned. <code>feature.isMany()</code> has to be
+   *          <code>true</code>.
+   * @return the list mapping corresponding to the feature.
+   */
+  public IListMapping getListMapping(EStructuralFeature feature);
+
+  /**
+   * @since 3.0
+   */
+  public List<IListMapping> getListMappings();
+
+  /**
+   * @since 4.0
+   */
+  public List<ITypeMapping> getValueMappings();
+
+  /**
+   * Read a revision. The branch and timestamp to be read are derived from the branchPoint which is set to the Revision.
+   * Note that non-audit stores only support {@link CDOBranchPoint#UNSPECIFIED_DATE} and non-branching stores only
+   * support the main branch.
+   * 
+   * @param accessor
+   *          the accessor to use.
+   * @param revision
+   *          the revision object into which the data should be read. The revision has to be have its ID set to the
+   *          requested object's ID. The version is ignored, as the version parameter is used to determine the version
+   *          to be read.
+   * @param listChunk
+   *          the chunk size to read attribute lists.
+   * @return <code>true</code>, if the revision has been found and read correctly. <code>false</code> if the revision
+   *         could not be found. In this case, the content of <code>revision</code> is undefined.
+   */
+  public boolean readRevision(IDBStoreAccessor accessor, InternalCDORevision revision, int listChunk);
+
+  /**
+   * Write the revision data to the database.
+   * 
+   * @param accessor
+   *          the accessor to use.
+   * @param revision
+   *          the revision to write.
+   * @param mapType
+   *          <code>true</code> if the type of the object is supposed to be mapped, <code>false</code> otherwise.
+   * @param revise
+   *          <code>true</code> if the previous revision is supposed to be revised, <code>false</code> otherwise.
+   * @param monitor
+   *          the monitor to indicate progress.
+   * @since 4.0
+   */
+  public void writeRevision(IDBStoreAccessor accessor, InternalCDORevision revision, boolean mapType, boolean revise,
+      OMMonitor monitor);
+
+  /**
+   * Detaches (deletes) a CDO object leaving a "ghost" revision behind.
+   * 
+   * @param accessor
+   *          the accessor to use.
+   * @param id
+   *          the id to revise.
+   * @param version
+   *          the last valid version.
+   * @param timeStamp
+   *          the timestamp of detach.
+   * @param monitor
+   *          the monitor to indicate progress.
+   * @since 3.0
+   */
+  public void detachObject(IDBStoreAccessor accessor, CDOID id, int version, CDOBranch branch, long timeStamp,
+      OMMonitor monitor);
+
+  /**
+   * Create a prepared statement which returns all IDs of instances of the corresponding class.
+   * 
+   * @param accessor
+   *          the accessor to use to create the statement
+   * @return the prepared statement ready to be executed using <code>result.executeQuery()</code>.
+   * @since 3.0
+   */
+  public PreparedStatement createObjectIDStatement(IDBStoreAccessor accessor);
+
+  /**
+   * Create a prepared statement which returns all IDs of instances of the corresponding class.
+   * 
+   * @param accessor
+   *          the accessor to use to create the statement
+   * @param folderId
+   *          the ID of the containing folder. <code>0</code> means none.
+   * @param name
+   *          the name of the resource node to look up
+   * @param exactMatch
+   *          if <code>true</code>, <code>name</code> must match exactly, otherwise all resource nodes starting with
+   *          <code>name</code> are returned.
+   * @param branchPoint
+   *          a branchPoint (branch and timestamp). A timestamp in the past if past versions should be looked up. In
+   *          case of no audit support, this must be {@link CDORevision#UNSPECIFIED_DATE}. In case of non branching
+   *          support the branch id must be equal to {@link CDOBranch#MAIN_BRANCH_ID}.
+   * @return the prepared statement ready to be executed using <code>result.executeQuery()</code>.
+   * @throws ImplementationError
+   *           if called on a mapping which does not map an <code>EClass instanceof CDOResourceNode</code>.
+   * @since 3.0
+   */
+  public PreparedStatement createResourceQueryStatement(IDBStoreAccessor accessor, CDOID folderId, String name,
+      boolean exactMatch, CDOBranchPoint branchPoint);
+
+  /**
+   * Passes all revisions of the store to the {@link CDORevisionHandler handler} if <b>all</b> of the following
+   * conditions are met:
+   * <ul>
+   * <li>The <code>branch</code> parameter is <code>null</code> or equal to <code>revision.getBranch()</code>.
+   * <li>The <code>timeStamp</code> parameter is {@link CDOBranchPoint#UNSPECIFIED_DATE} or equal to
+   * <code>revision.getTimeStamp()</code>.
+   * </ul>
+   * 
+   * @see IMappingStrategy#handleRevisions(IDBStoreAccessor, org.eclipse.emf.ecore.EClass, CDOBranch, long, boolean,
+   *      CDORevisionHandler)
+   * @since 4.0
+   */
+  public void handleRevisions(IDBStoreAccessor accessor, CDOBranch branch, long timeStamp, boolean exactTime,
+      CDORevisionHandler handler);
+
+  /**
+   * Returns a set of CDOIDs that have at least one revision in any of the passed branches and time ranges.
+   * DetachedCDORevisions must also be considered!
+   * 
+   * @see IStoreAccessor#readChangeSet(OMMonitor, CDOChangeSetSegment...)
+   * @since 3.0
+   */
+  public Set<CDOID> readChangeSet(IDBStoreAccessor accessor, CDOChangeSetSegment[] segments);
+
+  /**
+   * Retrieve cross-references from DB
+   * 
+   * @param idString
+   *          a string of the form "(id1, id2, id3, ...)" which can be used directly in SQL to form the where-part
+   *          "SELECT * FROM foobar WHERE foobar.target IN [idString]".
+   * @see IStoreAccessor#queryXRefs(QueryXRefsContext)
+   * @since 4.0
+   */
+  public boolean queryXRefs(IDBStoreAccessor accessor, QueryXRefsContext context, String idString);
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/IClassMappingAuditSupport.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/IClassMappingAuditSupport.java
new file mode 100644
index 0000000..5a1b13f
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/IClassMappingAuditSupport.java
@@ -0,0 +1,44 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - 271444: [DB] Multiple refactorings bug 271444
+ */
+package org.eclipse.emf.cdo.server.db.mapping;
+
+import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+
+/**
+ * Interface which complements {@link IClassMapping} with methods to facilitate audit support.
+ * 
+ * @see IMappingStrategy#hasAuditSupport()
+ * @author Eike Stepper
+ * @author Stefan Winkler
+ * @since 2.0
+ */
+public interface IClassMappingAuditSupport
+{
+  /**
+   * Read a specific version of a revision. If this method returns <code>true</code> it is guaranteed that
+   * <code>revision.getVersion() == version</code>
+   * 
+   * @param storeAccessor
+   *          the accessor to use.
+   * @param revision
+   *          the revision object into which the data should be read. The revision has to be have its ID set to the
+   *          requested object's ID. The version is ignored, as the version parameter is used to determine the version
+   *          to be read.
+   * @param listChunk
+   *          the chunk size to read attribute lists.
+   * @return <code>true</code>, if the revision has been found and read correctly. <code>false</code> if the revision
+   *         could not be found. In this case, the content of <code>revision</code> is undefined.
+   * @since 3.0
+   */
+  public boolean readRevisionByVersion(IDBStoreAccessor storeAccessor, InternalCDORevision revision, int listChunk);
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/IClassMappingDeltaSupport.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/IClassMappingDeltaSupport.java
new file mode 100644
index 0000000..86bf12e
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/IClassMappingDeltaSupport.java
@@ -0,0 +1,43 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - 271444: [DB] Multiple refactorings bug 271444
+ */
+package org.eclipse.emf.cdo.server.db.mapping;
+
+import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionDelta;
+
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+
+/**
+ * Interface which complements {@link IClassMapping} with methods to facilitate revision delta support.
+ * 
+ * @see IMappingStrategy#hasDeltaSupport()
+ * @author Eike Stepper
+ * @author Stefan Winkler
+ * @since 2.0
+ */
+public interface IClassMappingDeltaSupport
+{
+  /**
+   * Write a revision delta.
+   * 
+   * @param accessor
+   *          the accessor to use.
+   * @param delta
+   *          the delta to write.
+   * @param created
+   *          the creation timestamp of the new version
+   * @param monitor
+   *          the monitor to report progress.
+   */
+  public void writeRevisionDelta(IDBStoreAccessor accessor, InternalCDORevisionDelta delta, long created,
+      OMMonitor monitor);
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/IListMapping.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/IListMapping.java
new file mode 100644
index 0000000..bb09fa2
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/IListMapping.java
@@ -0,0 +1,113 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - major refactoring
+ */
+package org.eclipse.emf.cdo.server.db.mapping;
+
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.server.IStoreAccessor;
+import org.eclipse.emf.cdo.server.IStoreAccessor.QueryXRefsContext;
+import org.eclipse.emf.cdo.server.IStoreChunkReader.Chunk;
+import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
+import org.eclipse.emf.cdo.server.db.IDBStoreChunkReader;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDOList;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+
+import org.eclipse.net4j.db.ddl.IDBTable;
+
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Interface for mapping features with <code>isMany() == true</code>.
+ * 
+ * @author Eike Stepper
+ * @author Stefan Winkler
+ * @since 2.0
+ */
+public interface IListMapping
+{
+  /**
+   * Return the mapped feature.
+   * 
+   * @return the mapped feature.
+   */
+  public EStructuralFeature getFeature();
+
+  /**
+   * Returns all DB tables which are used by this feature.
+   * 
+   * @return a collection of all tables of this feature.
+   */
+  public Collection<IDBTable> getDBTables();
+
+  /**
+   * Write a complete list of values to the database.
+   * 
+   * @param accessor
+   *          the accessor to use.
+   * @param revision
+   *          the revision containing the list to be written.
+   */
+  public void writeValues(IDBStoreAccessor accessor, InternalCDORevision revision);
+
+  /**
+   * Read the list size and the complete list or the first part of it.
+   * 
+   * @param accessor
+   *          the accessor to use.
+   * @param revision
+   *          the revision into which the list values should be read.
+   * @param listChunk
+   *          indicating the lazy loading behavior: {@link CDORevision#UNCHUNKED} means that the whole list should be
+   *          read. Else, if <code>listChunk >= 0</code>, the list is filled with {@link InternalCDOList#UNINITIALIZED}
+   *          and only the first <code>listChunk</code> values are read.
+   */
+  public void readValues(IDBStoreAccessor accessor, InternalCDORevision revision, int listChunk);
+
+  /**
+   * Used to load-on-demand chunks of a list.
+   * 
+   * @param dbStoreChunkReader
+   *          the chunkReader to use
+   * @param chunks
+   *          the chunks to read
+   * @param where
+   *          the where-clause to use in order to read the chunks.
+   */
+  public void readChunks(IDBStoreChunkReader dbStoreChunkReader, List<Chunk> chunks, String where);
+
+  /**
+   * Hook with which a list mapping is notified that a containing object has been revised. Can be implemented in order
+   * to clean up lists of revised objects.
+   * 
+   * @param accessor
+   *          the accessor to use.
+   * @param id
+   *          the ID of the object which has been revised.
+   * @param revised
+   *          the timestamp at which the object was revised.
+   * @since 3.0
+   */
+  public void objectDetached(IDBStoreAccessor accessor, CDOID id, long revised);
+
+  /**
+   * Retrieve cross-references from DB.
+   * 
+   * @see IClassMapping#queryXRefs(IDBStoreAccessor, IStoreAccessor.QueryXRefsContext, String)
+   * @see IStoreAccessor#queryXRefs(IStoreAccessor.QueryXRefsContext)
+   * @since 4.0
+   */
+  public boolean queryXRefs(IDBStoreAccessor accessor, String mainTableName, String mainTableWhere,
+      QueryXRefsContext context, String idString);
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/IListMappingDeltaSupport.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/IListMappingDeltaSupport.java
new file mode 100644
index 0000000..5ed5698
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/IListMappingDeltaSupport.java
@@ -0,0 +1,47 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - 271444: [DB] Multiple refactorings bug 271444
+ *    Stefan Winkler - Bug 329025: [DB] Support branching for range-based mapping strategy
+ */
+package org.eclipse.emf.cdo.server.db.mapping;
+
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.revision.delta.CDOListFeatureDelta;
+import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
+
+/**
+ * Interface to complement {@link IListMapping} in order to provide list delta processing support.
+ * 
+ * @author Eike Stepper
+ * @author Stefan Winkler
+ * @since 2.0
+ */
+public interface IListMappingDeltaSupport
+{
+  /**
+   * Process a set of CDOFeatureDeltas for a many-valued feature.
+   * 
+   * @param accessor
+   *          the accessor to use
+   * @param id
+   *          the ID of the revision affected
+   * @param oldVersion
+   *          the original version of the revision
+   * @param newVersion
+   *          the new revision of the revision (after the change)
+   * @param created
+   *          the creation date for the new revision
+   * @param delta
+   *          the {@link CDOListFeatureDelta} which contains the list deltas.
+   * @since 4.0
+   */
+  public void processDelta(IDBStoreAccessor accessor, CDOID id, int branchId, int oldVersion, int newVersion,
+      long created, CDOListFeatureDelta delta);
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/IMappingStrategy.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/IMappingStrategy.java
new file mode 100644
index 0000000..90c6516
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/IMappingStrategy.java
@@ -0,0 +1,348 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - 271444: [DB] Multiple refactorings bug 271444
+ */
+package org.eclipse.emf.cdo.server.db.mapping;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.model.CDOClassifierRef;
+import org.eclipse.emf.cdo.common.protocol.CDODataInput;
+import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
+import org.eclipse.emf.cdo.common.revision.CDORevisionHandler;
+import org.eclipse.emf.cdo.server.IStoreAccessor;
+import org.eclipse.emf.cdo.server.IStoreAccessor.QueryResourcesContext;
+import org.eclipse.emf.cdo.server.IStoreAccessor.QueryXRefsContext;
+import org.eclipse.emf.cdo.server.db.IDBStore;
+import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
+import org.eclipse.emf.cdo.server.internal.db.DBStore;
+import org.eclipse.emf.cdo.spi.common.commit.CDOChangeSetSegment;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit;
+
+import org.eclipse.net4j.db.IDBAdapter;
+import org.eclipse.net4j.util.collection.CloseableIterator;
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.ENamedElement;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+import java.io.IOException;
+import java.sql.Connection;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * The mapping strategy acts as a connection between the DBStore and the database management (and OR-mapping) classes.
+ * The {@link DBStore} uses methods of this interface to create and lookup mappings (or mappers, as they could also be
+ * named as such) and to get properties and informations about the mappings used. The mapping classes (e.g., instances
+ * of IClassMapping and IListMapping) also use this class as a central point of information and as a resource of common
+ * functionalities.
+ * 
+ * @author Eike Stepper
+ * @author Stefan Winkler
+ * @since 2.0
+ */
+public interface IMappingStrategy
+{
+  /**
+   * Name of the integer property that configures the maximum length for table names. A value of zero indicates the
+   * value of the {@link IDBAdapter#getMaxTableNameLength() db adapter} to be used.
+   */
+  public static final String PROP_MAX_TABLE_NAME_LENGTH = "maxTableNameLength"; //$NON-NLS-1$
+
+  /**
+   * Name of the integer property that configures the maximum length for column names. A value of zero indicates the
+   * value of the {@link IDBAdapter#getMaxFieldNameLength() db adapter} to be used.
+   */
+  public static final String PROP_MAX_FIELD_NAME_LENGTH = "maxFieldNameLength"; //$NON-NLS-1$
+
+  /**
+   * Name of the String property that specifies a common prefix for table names.
+   */
+  public static final String PROP_TABLE_NAME_PREFIX = "tableNamePrefix"; //$NON-NLS-1$
+
+  /**
+   * Name of the boolean property that configures whether the table names are made of simple class names or of qualified
+   * class names.
+   */
+  public static final String PROP_QUALIFIED_NAMES = "qualifiedNames"; //$NON-NLS-1$
+
+  /**
+   * Name of the boolean property that configures whether table names and column names are always suffixed with the
+   * internal DBID or only in cases where generated names violate the naming constraints of the underlying backend.
+   */
+  public static final String PROP_FORCE_NAMES_WITH_ID = "forceNamesWithID"; //$NON-NLS-1$
+
+  /**
+   * Name of the integer property that configures the size of the object type in-memory cache. Possible configuration
+   * values are:
+   * <ul>
+   * <li>0 (zero). Don't use memory caching.
+   * <li>&gt;0. Use memory caching with the cache size given.
+   * </ul>
+   * Default is a memory cache size of 10,000,000.
+   * <p>
+   * 
+   * @since 4.0
+   */
+  public static final String PROP_OBJECT_TYPE_CACHE_SIZE = "objectTypeCacheSize"; //$NON-NLS-1$
+
+  /**
+   * @return the store, this MappingStrategy instance belongs to.
+   */
+  public IDBStore getStore();
+
+  /**
+   * Set the store to which this MappingStrategy instance belongs. Should only be called by the {@link DBStore}, and
+   * only once to initialize the connection between {@link DBStore} and mapping strategy.
+   * 
+   * @param dbStore
+   *          the DBStore instance to which this MappingStrategy instance belongs.
+   */
+  public void setStore(IDBStore dbStore);
+
+  /**
+   * Factory for value mappings of single-valued attributes.
+   * 
+   * @param feature
+   *          the feature for which a mapping should be created. It must hold <code>feature.isMany() == false</code>.
+   * @return the mapping created.
+   */
+  public ITypeMapping createValueMapping(EStructuralFeature feature);
+
+  /**
+   * Factory for value mappings of multi-valued-attributes.
+   * 
+   * @param containingClass
+   *          the class containing the feature.
+   * @param feature
+   *          the feature for which a mapping should be created. It must hold <code>feature.isMany() == true</code>.
+   */
+  public IListMapping createListMapping(EClass containingClass, EStructuralFeature feature);
+
+  /**
+   * Create a suitable table name which can be used to map the given element. Should only be called by mapping classes.
+   * 
+   * @param element
+   *          the element for which the name should be created. It must hold:
+   *          <code>element instanceof EClass || element instanceof EPackage</code>.
+   * @return the created table name. It is guaranteed that the table name is compatible with the chosen database.
+   */
+  public String getTableName(ENamedElement element);
+
+  /**
+   * Create a suitable table name which can be used to map the given element. Should only be called by mapping classes.
+   * Should only be called by mapping classes.
+   * 
+   * @param containingClass
+   *          the class containeng the feature.
+   * @param feature
+   *          the feature for which the table name should be created.
+   * @return the created table name. It is guaranteed that the table name is compatible with the chosen database.
+   */
+  public String getTableName(EClass containingClass, EStructuralFeature feature);
+
+  /**
+   * Create a suitable column name which can be used to map the given element. Should only be called by mapping classes.
+   * 
+   * @param feature
+   *          the feature for which the column name should be created.
+   * @return the created column name. It is guaranteed that the name is compatible with the chosen database.
+   */
+  public String getFieldName(EStructuralFeature feature);
+
+  /**
+   * Create and initialize the mapping infrastructure for the given packages. Should be called from the DBStore or the
+   * DBStoreAccessor.
+   * 
+   * @param connection
+   *          the connection to use.
+   * @param packageUnits
+   *          the packages whose elements should be mapped.
+   * @param monitor
+   *          the monitor to report progress.
+   */
+  public void createMapping(Connection connection, InternalCDOPackageUnit[] packageUnits, OMMonitor monitor);
+
+  /**
+   * Remove the mapping infrastructure for the given packages. Should be called from the DBStore or the DBStoreAccessor.
+   * 
+   * @param connection
+   *          the connection to use.
+   * @param packageUnits
+   *          the packages for which the mappings should be removed
+   * @since 4.0
+   */
+  // Bugzilla 298632
+  public void removeMapping(Connection connection, InternalCDOPackageUnit[] packageUnits);
+
+  /**
+   * Look up an existing class mapping for the given class. Before this method is called, the class mapping must have
+   * been initialized by calling {@link #createMapping(Connection, InternalCDOPackageUnit[], OMMonitor)} on its
+   * containing package.
+   * 
+   * @param eClass
+   *          the class to look up.
+   * @return the class mapping.
+   */
+  public IClassMapping getClassMapping(EClass eClass);
+
+  /**
+   * Returns all class mappings of this strategy.
+   * 
+   * @since 4.0
+   */
+  public Map<EClass, IClassMapping> getClassMappings();
+
+  /**
+   * Returns all class mappings of this strategy.
+   * 
+   * @since 4.0
+   */
+  public Map<EClass, IClassMapping> getClassMappings(boolean createOnDemand);
+
+  /**
+   * Query if this mapping supports revision deltas. <br>
+   * If this method returns <code>true</code>, it is guaranteed that all class mappings returned by
+   * {@link #getClassMapping(EClass)} implement {@link IClassMappingDeltaSupport}.
+   * 
+   * @return <code>true</code> if revision deltas are supported, <code>false</code> else.
+   */
+  public boolean hasDeltaSupport();
+
+  /**
+   * Query if this mapping supports audits. <br>
+   * If this method returns <code>true</code>, it is guaranteed that all class mappings returned by
+   * {@link #getClassMapping(EClass)} implement {@link IClassMappingAuditSupport}.
+   * 
+   * @return <code>true</code> if audits are supported, <code>false</code> else.
+   */
+  public boolean hasAuditSupport();
+
+  /**
+   * Query if this mapping supports branches. <br>
+   * 
+   * @return <code>true</code> if branches are supported, <code>false</code> else.
+   * @since 3.0
+   */
+  public boolean hasBranchingSupport();
+
+  /**
+   * Executes a resource query.
+   * 
+   * @param accessor
+   *          the accessor to use.
+   * @param context
+   *          the context from which the query parameters are read and to which the result is written.
+   */
+  public void queryResources(IDBStoreAccessor accessor, QueryResourcesContext context);
+
+  /**
+   * Executes a cross reference query.
+   * 
+   * @param accessor
+   *          the accessor to use.
+   * @param context
+   *          the context from which the query parameters are read and to which the result is written.
+   * @since 3.0
+   */
+  public void queryXRefs(IDBStoreAccessor accessor, QueryXRefsContext context);
+
+  /**
+   * Read the type (i.e. class) of the object referred to by a given ID.
+   * 
+   * @param accessor
+   *          the accessor to use to look up the type.
+   * @param id
+   *          the ID of the object for which the type is to be determined.
+   * @return the type of the object.
+   */
+  public CDOClassifierRef readObjectType(IDBStoreAccessor accessor, CDOID id);
+
+  /**
+   * Get an iterator over all instances of objects in the store.
+   * 
+   * @param accessor
+   *          the accessor to use.
+   * @return the iterator.
+   */
+  public CloseableIterator<CDOID> readObjectIDs(IDBStoreAccessor accessor);
+
+  /**
+   * Return the maximum object id used in the store. This is used by the DBStore if a previous crash is discovered
+   * during the startup process. Should only be called by the DBStore and only during startup.
+   * 
+   * @param dbAdapter
+   *          the dbAdapter to use to access the database
+   * @param connection
+   *          the connection to use to access the database
+   * @since 4.0
+   */
+  public void repairAfterCrash(IDBAdapter dbAdapter, Connection connection);
+
+  /**
+   * Returns the configuration properties of this mapping strategy.
+   * 
+   * @since 4.0
+   */
+  public Map<String, String> getProperties();
+
+  /**
+   * Set configuration properties for this mapping strategy. Should only be called by the factory creating the mapping
+   * strategy instance.
+   * 
+   * @param properties
+   *          the configuration properties to set.
+   */
+  public void setProperties(Map<String, String> properties);
+
+  /**
+   * Passes all revisions of the store to the {@link CDORevisionHandler handler} if <b>all</b> of the following
+   * conditions are met:
+   * <ul>
+   * <li>The <code>eClass</code> parameter is <code>null</code> or equal to <code>revision.getEClass()</code>.
+   * <li>The <code>branch</code> parameter is <code>null</code> or equal to <code>revision.getBranch()</code>.
+   * <li>The <code>timeStamp</code> parameter is {@link CDOBranchPoint#UNSPECIFIED_DATE} or equal to
+   * <code>revision.getTimeStamp()</code>.
+   * </ul>
+   * 
+   * @since 4.0
+   */
+  public void handleRevisions(IDBStoreAccessor accessor, EClass eClass, CDOBranch branch, long timeStamp,
+      boolean exactTime, CDORevisionHandler handler);
+
+  /**
+   * Returns a set of CDOIDs that have at least one revision in any of the passed branches and time ranges.
+   * DetachedCDORevisions must also be considered!
+   * 
+   * @see IStoreAccessor#readChangeSet(OMMonitor, CDOChangeSetSegment...)
+   * @since 4.0
+   */
+  public Set<CDOID> readChangeSet(IDBStoreAccessor accessor, OMMonitor monitor, CDOChangeSetSegment[] segments);
+
+  /**
+   * @since 3.0
+   */
+  public void rawExport(IDBStoreAccessor accessor, CDODataOutput out, int lastReplicatedBranchID, int lastBranchID,
+      long lastReplicatedCommitTime, long lastCommitTime) throws IOException;
+
+  /**
+   * @since 4.0
+   */
+  public void rawImport(IDBStoreAccessor accessor, CDODataInput in, long fromCommitTime, long toCommitTime,
+      OMMonitor monitor) throws IOException;
+
+  /**
+   * @since 4.0
+   */
+  public String getListJoin(String attrTable, String listTable);
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/ITypeMapping.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/ITypeMapping.java
new file mode 100644
index 0000000..c6d463c
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/ITypeMapping.java
@@ -0,0 +1,278 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - major refactoring
+ *    Christopher Albert - 254455: [DB] Support FeatureMaps bug 254455
+ */
+package org.eclipse.emf.cdo.server.db.mapping;
+
+import org.eclipse.emf.cdo.server.internal.db.mapping.TypeMappingRegistry;
+import org.eclipse.emf.cdo.server.internal.db.mapping.TypeMappingUtil;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+
+import org.eclipse.net4j.db.DBType;
+import org.eclipse.net4j.db.ddl.IDBField;
+import org.eclipse.net4j.db.ddl.IDBTable;
+import org.eclipse.net4j.util.factory.IFactory;
+
+import org.eclipse.emf.ecore.EClassifier;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Collection;
+
+/**
+ * Mapping of single values to and from the database.
+ * 
+ * @author Eike Stepper
+ * @author Stefan Winkler
+ * @since 2.0
+ */
+public interface ITypeMapping
+{
+  /**
+   * @return The feature which is associated with this mapping.
+   */
+  public EStructuralFeature getFeature();
+
+  /**
+   * @return The db field which is associated with this mapping.
+   */
+  public IDBField getField();
+
+  /**
+   * @return The db type which is associated with this mapping.
+   * @since 3.0
+   */
+  public DBType getDBType();
+
+  /**
+   * @since 4.0
+   */
+  public void setMappingStrategy(IMappingStrategy mappingStrategy);
+
+  /**
+   * @since 4.0
+   */
+  public void setFeature(EStructuralFeature feature);
+
+  /**
+   * @since 4.0
+   */
+  public void setDBType(DBType dbType);
+
+  /**
+   * Creates the DBField and adds it to the given table. The name of the DBField is derived from the feature.
+   * 
+   * @param table
+   *          the table to add this field to.
+   */
+  public void createDBField(IDBTable table);
+
+  /**
+   * Creates the DBField and adds it to the given table. The name of the DBField is explicitly determined by the
+   * corresponding parameter.
+   * 
+   * @param table
+   *          the table to add this field to.
+   * @param fieldName
+   *          the name for the DBField.
+   */
+  public void createDBField(IDBTable table, String fieldName);
+
+  /**
+   * Sets the DBField. The name of the DBField is explicitly determined by the corresponding parameter.
+   * 
+   * @param table
+   *          the table to add this field to.
+   * @param fieldName
+   *          the name for the DBField.
+   * @since 3.0
+   */
+  public void setDBField(IDBTable table, String fieldName);
+
+  /**
+   * Set the given value to the JDBC {@link PreparedStatement} using an appropriate <code>setXxx</code> method.
+   * 
+   * @param stmt
+   *          the prepared statement to set the value
+   * @param index
+   *          the index to use for the <code>setXxx</code> method.
+   * @param value
+   *          the value to set.
+   * @throws SQLException
+   *           if the <code>setXxx</code> throws it.
+   */
+  public void setValue(PreparedStatement stmt, int index, Object value) throws SQLException;
+
+  /**
+   * Set the feature's default value to the JDBC {@link PreparedStatement} using an appropriate <code>setXxx</code>
+   * method.
+   * 
+   * @param stmt
+   *          the prepared statement to set the value
+   * @param index
+   *          the index to use for the <code>setXxx</code> method.
+   * @throws SQLException
+   *           if the <code>setXxx</code> throws it.
+   * @since 3.0
+   */
+  public void setDefaultValue(PreparedStatement stmt, int index) throws SQLException;
+
+  /**
+   * Set a value of the given revision to the JDBC {@link PreparedStatement} using an appropriate <code>setXxx</code>
+   * method. The feature from which the value is taken is determined by {@link #getFeature()}.
+   * 
+   * @param stmt
+   *          the prepared statement to set the value
+   * @param index
+   *          the index to use for the <code>setXxx</code> method.
+   * @param value
+   *          the revision to get the value to set from.
+   * @throws SQLException
+   *           if the <code>setXxx</code> throws it.
+   */
+  public void setValueFromRevision(PreparedStatement stmt, int index, InternalCDORevision value) throws SQLException;
+
+  /**
+   * Read the value from a {@link ResultSet} and convert it from the DB to the CDO representation. The resultSet field
+   * to read from is determined automatically by the internal {@link #getField()} name.
+   * 
+   * @param resultSet
+   *          the result set to read from
+   * @return the read value
+   * @throws SQLException
+   *           if reading the value throws an SQLException
+   * @since 3.0
+   */
+  public Object readValue(ResultSet resultSet) throws SQLException;
+
+  /**
+   * Read a value from a {@link ResultSet}, convert it from the DB to the CDO representation and set it to the feature
+   * of the revision. The feature is determined by getFeature() The resultSet field to read from is determined
+   * automatically by the internal {@link #getField()} name.
+   * 
+   * @param resultSet
+   *          the result set to read from
+   * @param revision
+   *          the revision to which the value should be set.
+   * @throws SQLException
+   *           if reading the value throws an SQLException
+   * @since 3.0
+   */
+  public void readValueToRevision(ResultSet resultSet, InternalCDORevision revision) throws SQLException;
+
+  /**
+   * A descriptor which describes one type mapping class. The descriptor is encoded in the factoryType which is used as
+   * a string description for the extension point mechanism. Translations and instantiations can be done using the
+   * methods in {@link TypeMappingUtil}.
+   * 
+   * @author Stefan Winkler
+   * @since 4.0
+   */
+  public interface Descriptor
+  {
+    /**
+     * The factoryType of the factory which can create the type mapping
+     */
+    public String getFactoryType();
+
+    /**
+     * The ID of the described type mapping.
+     */
+    public String getID();
+
+    /**
+     * The source (i.e., model) type that can be mapped by the type mapping.
+     */
+    public EClassifier getEClassifier();
+
+    /**
+     * The target (i.e., db) type that can be mapped by the type mapping.
+     */
+    public DBType getDBType();
+
+  }
+
+  /**
+   * A global (singleton) registry which collects all available type mappings which are either available in the CDO
+   * core, as declared extensions, or registered manually.
+   * 
+   * @author Stefan Winkler
+   * @since 4.0
+   */
+  public interface Registry
+  {
+    /**
+     * The one global (singleton) registry instance.
+     */
+    public static Registry INSTANCE = new TypeMappingRegistry();
+
+    /**
+     * Register a type mapping by descriptor.
+     */
+    public void registerTypeMapping(ITypeMapping.Descriptor descriptor);
+
+    /**
+     * Provides a list of all DBTypes for which type mappings exist in the registry. This is used in feature map tables
+     * to create columns for all of these types.
+     */
+    public Collection<DBType> getDefaultFeatureMapDBTypes();
+  }
+
+  /**
+   * A provider for type mapping information. This provider is used by the {@link TypeMappingRegistry} to create an
+   * {@link ITypeMapping} instance suitable for a given feature and DB field. Usually, one factory is responsible for
+   * one type mapping.
+   * 
+   * @author Stefan Winkler
+   * @since 4.0
+   */
+  public interface Provider
+  {
+    /**
+     * The one global (singleton) provider instance.
+     */
+    public static Provider INSTANCE = (Provider)Registry.INSTANCE;
+
+    /**
+     * Create an {@link ITypeMapping} implementation.
+     * 
+     * @param mappingStrategy
+     *          the mapping strategy
+     * @param feature
+     *          the feature the new type mapping shall be responsible for
+     * @return the newly created {@link ITypeMapping} instance
+     */
+    public ITypeMapping createTypeMapping(IMappingStrategy mappingStrategy, EStructuralFeature feature);
+  }
+
+  /**
+   * A factory for typeMappings. This is a regular Net4j factory registered by the respective extension point. It
+   * enhances the regular factory using a descriptor which is translated from and to the factoryType by the methods in
+   * {@link TypeMappingUtil}.
+   * 
+   * @author Stefan Winkler
+   * @since 4.0
+   */
+  public interface Factory extends IFactory
+  {
+    /**
+     * The Net4j factory product group for type mappings
+     */
+    public static final String PRODUCT_GROUP = "org.eclipse.emf.cdo.server.db.typeMappings";
+
+    /**
+     * Return the descriptor of the kind of type mapping created by this factory.
+     */
+    public ITypeMapping.Descriptor getDescriptor();
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/package-info.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/package-info.java
new file mode 100644
index 0000000..cec7a93
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/mapping/package-info.java
@@ -0,0 +1,15 @@
+/*

+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ * 

+ * Contributors:

+ *    Eike Stepper - initial API and implementation

+ */

+

+/**

+ * Server concepts for dealing with mapping strategies and mappings for classes, lists and types.

+ */

+package org.eclipse.emf.cdo.server.db.mapping;

diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/package-info.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/package-info.java
new file mode 100644
index 0000000..53e5399
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/db/package-info.java
@@ -0,0 +1,15 @@
+/*

+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ * 

+ * Contributors:

+ *    Eike Stepper - initial API and implementation

+ */

+

+/**

+ * Server concepts for dealing with DB stores and accessors.

+ */

+package org.eclipse.emf.cdo.server.db;

diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/AbstractPreparedStatementCache.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/AbstractPreparedStatementCache.java
new file mode 100644
index 0000000..2ffd031
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/AbstractPreparedStatementCache.java
@@ -0,0 +1,47 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Stefan Winkler - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server.internal.db;
+
+import org.eclipse.emf.cdo.server.db.IPreparedStatementCache;
+
+import org.eclipse.net4j.util.lifecycle.Lifecycle;
+
+import java.sql.Connection;
+
+/**
+ * @author Stefan Winkler
+ * @since 2.0
+ */
+public abstract class AbstractPreparedStatementCache extends Lifecycle implements IPreparedStatementCache
+{
+  private Connection connection;
+
+  public AbstractPreparedStatementCache()
+  {
+  }
+
+  public final Connection getConnection()
+  {
+    return connection;
+  }
+
+  public final void setConnection(Connection connection)
+  {
+    checkInactive();
+    this.connection = connection;
+  }
+
+  @Override
+  protected void doBeforeActivate()
+  {
+    checkState(connection, "Must have valid connection to start"); //$NON-NLS-1$
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/CDODBSchema.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/CDODBSchema.java
new file mode 100644
index 0000000..dc3e19b
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/CDODBSchema.java
@@ -0,0 +1,267 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - 271444: [DB] Multiple refactorings bug 271444
+ *    Stefan Winkler - 249610: [DB] Support external references (Implementation)
+ *    Andre Dietisheim - bug 256649
+ *
+ */
+package org.eclipse.emf.cdo.server.internal.db;
+
+import org.eclipse.net4j.db.DBType;
+import org.eclipse.net4j.db.ddl.IDBField;
+import org.eclipse.net4j.db.ddl.IDBIndex;
+import org.eclipse.net4j.db.ddl.IDBTable;
+import org.eclipse.net4j.spi.db.DBSchema;
+
+/**
+ * @author Eike Stepper
+ */
+public class CDODBSchema extends DBSchema
+{
+  public static final CDODBSchema INSTANCE = new CDODBSchema();
+
+  /**
+   * DBTable cdo_properties
+   */
+  public static final IDBTable PROPERTIES = INSTANCE.addTable("cdo_properties"); //$NON-NLS-1$
+
+  public static final IDBField PROPERTIES_NAME = //
+  PROPERTIES.addField("name", DBType.VARCHAR, 255); //$NON-NLS-1$
+
+  public static final IDBField PROPERTIES_VALUE = //
+  PROPERTIES.addField("value", DBType.LONGVARCHAR); //$NON-NLS-1$
+
+  public static final IDBIndex INDEX_PROPERTIES_PK = //
+  PROPERTIES.addIndex(IDBIndex.Type.PRIMARY_KEY, PROPERTIES_NAME);
+
+  public static final String SQL_DELETE_PROPERTIES = "DELETE FROM " + PROPERTIES + " WHERE " + PROPERTIES_NAME + "=?"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+  public static final String SQL_INSERT_PROPERTIES = "INSERT INTO " + PROPERTIES + " (" + PROPERTIES_NAME + ", " //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+      + PROPERTIES_VALUE + ") VALUES (?, ?)"; //$NON-NLS-1$
+
+  public static final String SQL_SELECT_PROPERTIES = "SELECT " + PROPERTIES_VALUE + " FROM " + PROPERTIES + " WHERE " //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+      + PROPERTIES_NAME + "=?"; //$NON-NLS-1$
+
+  public static final String SQL_SELECT_ALL_PROPERTIES = "SELECT " + PROPERTIES_NAME + ", " + PROPERTIES_VALUE //$NON-NLS-1$ //$NON-NLS-2$
+      + " FROM " + PROPERTIES; //$NON-NLS-1$
+
+  /**
+   * DBTable cdo_package_units
+   */
+  public static final IDBTable PACKAGE_UNITS = INSTANCE.addTable("cdo_package_units"); //$NON-NLS-1$
+
+  public static final IDBField PACKAGE_UNITS_ID = //
+  PACKAGE_UNITS.addField("id", DBType.VARCHAR, 255); //$NON-NLS-1$
+
+  public static final IDBField PACKAGE_UNITS_ORIGINAL_TYPE = //
+  PACKAGE_UNITS.addField("original_type", DBType.INTEGER); //$NON-NLS-1$
+
+  public static final IDBField PACKAGE_UNITS_TIME_STAMP = //
+  PACKAGE_UNITS.addField("time_stamp", DBType.BIGINT); //$NON-NLS-1$
+
+  public static final IDBField PACKAGE_UNITS_PACKAGE_DATA = //
+  PACKAGE_UNITS.addField("package_data", DBType.BLOB); //$NON-NLS-1$
+
+  public static final IDBIndex INDEX_PACKAGE_UNITS_PK = //
+  PACKAGE_UNITS.addIndex(IDBIndex.Type.PRIMARY_KEY, PACKAGE_UNITS_ID);
+
+  /**
+   * DBTable cdo_packages
+   */
+  public static final IDBTable PACKAGE_INFOS = INSTANCE.addTable("cdo_package_infos"); //$NON-NLS-1$
+
+  public static final IDBField PACKAGE_INFOS_URI = //
+  PACKAGE_INFOS.addField("uri", DBType.VARCHAR, 255); //$NON-NLS-1$
+
+  public static final IDBField PACKAGE_INFOS_PARENT = //
+  PACKAGE_INFOS.addField("parent", DBType.VARCHAR, 255); //$NON-NLS-1$
+
+  public static final IDBField PACKAGE_INFOS_UNIT = //
+  PACKAGE_INFOS.addField("unit", DBType.VARCHAR, 255); //$NON-NLS-1$
+
+  public static final IDBIndex INDEX_PACKAGE_INFOS_PK = //
+  PACKAGE_INFOS.addIndex(IDBIndex.Type.PRIMARY_KEY, PACKAGE_INFOS_URI);
+
+  public static final IDBIndex INDEX_PACKAGE_INFOS_PARENT = //
+  PACKAGE_INFOS.addIndex(IDBIndex.Type.NON_UNIQUE, PACKAGE_INFOS_PARENT);
+
+  public static final IDBIndex INDEX_PACKAGE_INFOS_UNIT = //
+  PACKAGE_INFOS.addIndex(IDBIndex.Type.NON_UNIQUE, PACKAGE_INFOS_UNIT);
+
+  /**
+   * DBTable cdo_branches
+   */
+  public static final IDBTable BRANCHES = INSTANCE.addTable("cdo_branches"); //$NON-NLS-1$
+
+  public static final IDBField BRANCHES_ID = //
+  BRANCHES.addField("id", DBType.INTEGER); //$NON-NLS-1$
+
+  public static final IDBField BRANCHES_NAME = //
+  BRANCHES.addField("name", DBType.VARCHAR); //$NON-NLS-1$
+
+  public static final IDBField BRANCHES_BASE_BRANCH_ID = //
+  BRANCHES.addField("base_id", DBType.INTEGER); //$NON-NLS-1$
+
+  public static final IDBField BRANCHES_BASE_TIMESTAMP = //
+  BRANCHES.addField("base_time", DBType.BIGINT); //$NON-NLS-1$
+
+  public static final IDBIndex INDEX_BRANCHES_ID = //
+  BRANCHES.addIndex(IDBIndex.Type.PRIMARY_KEY, BRANCHES_ID);
+
+  public static final String SQL_CREATE_BRANCH = "INSERT INTO " + BRANCHES + " (" + BRANCHES_ID + ", " + BRANCHES_NAME //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+      + ", " + BRANCHES_BASE_BRANCH_ID + ", " + BRANCHES_BASE_TIMESTAMP + ") VALUES (?, ?, ?, ?)"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+  public static final String SQL_LOAD_BRANCH = "SELECT " + BRANCHES_NAME + ", " + BRANCHES_BASE_BRANCH_ID + ", " //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+      + BRANCHES_BASE_TIMESTAMP + " FROM " + BRANCHES + " WHERE " + BRANCHES_ID + "=?"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+  public static final String SQL_LOAD_SUB_BRANCHES = "SELECT " + BRANCHES_ID + ", " + BRANCHES_NAME + ", " //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+      + BRANCHES_BASE_TIMESTAMP + " FROM " + BRANCHES + " WHERE " + BRANCHES_BASE_BRANCH_ID + "=?"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+  public static final String SQL_LOAD_BRANCHES = "SELECT " + BRANCHES_ID + ", " + BRANCHES_NAME + ", " + //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+      BRANCHES_BASE_BRANCH_ID + ", " + BRANCHES_BASE_TIMESTAMP //$NON-NLS-1$
+      + " FROM " + BRANCHES + " WHERE " + BRANCHES_ID + " BETWEEN ? AND ? ORDER BY " + BRANCHES_ID; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+  /**
+   * DBTable cdo_commit_infos
+   */
+  public static final IDBTable COMMIT_INFOS = INSTANCE.addTable("cdo_commit_infos"); //$NON-NLS-1$
+
+  public static final IDBField COMMIT_INFOS_TIMESTAMP = //
+  COMMIT_INFOS.addField("commit_time", DBType.BIGINT); //$NON-NLS-1$
+
+  public static final IDBField COMMIT_INFOS_PREVIOUS_TIMESTAMP = //
+  COMMIT_INFOS.addField("previous_time", DBType.BIGINT); //$NON-NLS-1$
+
+  public static final IDBField COMMIT_INFOS_BRANCH = //
+  COMMIT_INFOS.addField("branch_id", DBType.INTEGER); //$NON-NLS-1$
+
+  public static final IDBField COMMIT_INFOS_USER = //
+  COMMIT_INFOS.addField("user_id", DBType.VARCHAR); //$NON-NLS-1$
+
+  public static final IDBField COMMIT_INFOS_COMMENT = //
+  COMMIT_INFOS.addField("commit_comment", DBType.VARCHAR); //$NON-NLS-1$
+
+  public static final IDBIndex INDEX_COMMIT_INFOS_PK = //
+  COMMIT_INFOS.addIndex(IDBIndex.Type.PRIMARY_KEY, COMMIT_INFOS_TIMESTAMP);
+
+  public static final IDBIndex INDEX_COMMIT_INFOS_BRANCH = //
+  COMMIT_INFOS.addIndex(IDBIndex.Type.NON_UNIQUE, COMMIT_INFOS_BRANCH);
+
+  public static final IDBIndex INDEX_COMMIT_INFOS_USER = //
+  COMMIT_INFOS.addIndex(IDBIndex.Type.NON_UNIQUE, COMMIT_INFOS_USER);
+
+  public static final String SQL_CREATE_COMMIT_INFO = "INSERT INTO " + COMMIT_INFOS + "(" + COMMIT_INFOS_TIMESTAMP //$NON-NLS-1$ //$NON-NLS-2$
+      + ", " + COMMIT_INFOS_PREVIOUS_TIMESTAMP + ", " + COMMIT_INFOS_BRANCH + ", " + COMMIT_INFOS_USER + ", " + COMMIT_INFOS_COMMENT + ") " //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+      + "VALUES (?, ?, ?, ?, ?)"; //$NON-NLS-1$
+
+  /**
+   * DBTable cdo_lobs
+   */
+  public static final IDBTable LOBS = INSTANCE.addTable("cdo_lobs"); //$NON-NLS-1$
+
+  public static final IDBField LOBS_ID = //
+  LOBS.addField("id", DBType.VARCHAR, 64); //$NON-NLS-1$
+
+  public static final IDBField LOBS_SIZE = //
+  LOBS.addField("size", DBType.BIGINT); //$NON-NLS-1$
+
+  public static final IDBField LOBS_BDATA = //
+  LOBS.addField("bdata", DBType.BLOB); //$NON-NLS-1$
+
+  public static final IDBField LOBS_CDATA = //
+  LOBS.addField("cdata", DBType.CLOB); //$NON-NLS-1$
+
+  public static final IDBIndex INDEX_LOBS_ID = //
+  LOBS.addIndex(IDBIndex.Type.PRIMARY_KEY, LOBS_ID);
+
+  public static final String SQL_QUERY_LOBS = "SELECT 1 FROM " + CDODBSchema.LOBS + " WHERE " + CDODBSchema.LOBS_ID + "=?"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+  public static final String SQL_HANDLE_LOBS = "SELECT " + CDODBSchema.LOBS_ID + ", " + CDODBSchema.LOBS_SIZE + ", " + CDODBSchema.LOBS_BDATA + ", " + CDODBSchema.LOBS_CDATA + " FROM " + CDODBSchema.LOBS; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+
+  public static final String SQL_LOAD_LOB = "SELECT " + CDODBSchema.LOBS_SIZE + ", " + CDODBSchema.LOBS_BDATA + ", " + CDODBSchema.LOBS_CDATA + " FROM " + CDODBSchema.LOBS + " WHERE " + CDODBSchema.LOBS_ID + "=?"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
+
+  public static final String SQL_WRITE_BLOB = "INSERT INTO " + CDODBSchema.LOBS + "(" + CDODBSchema.LOBS_ID + ", " + CDODBSchema.LOBS_SIZE + ", " + CDODBSchema.LOBS_BDATA + ") VALUES(?, ?, ?)"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+
+  public static final String SQL_WRITE_CLOB = "INSERT INTO " + CDODBSchema.LOBS + "(" + CDODBSchema.LOBS_ID + ", " + CDODBSchema.LOBS_SIZE + ", " + CDODBSchema.LOBS_CDATA + ") VALUES(?, ?, ?)"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+
+  /**
+   * Name of object table
+   */
+  public static final String CDO_OBJECTS = "cdo_objects"; //$NON-NLS-1$
+
+  /**
+   * Field names of attribute tables
+   */
+  public static final String ATTRIBUTES_ID = "cdo_id"; //$NON-NLS-1$
+
+  public static final String ATTRIBUTES_BRANCH = "cdo_branch"; //$NON-NLS-1$
+
+  public static final String ATTRIBUTES_VERSION = "cdo_version"; //$NON-NLS-1$
+
+  public static final String ATTRIBUTES_CLASS = "cdo_class"; //$NON-NLS-1$
+
+  public static final String ATTRIBUTES_CREATED = "cdo_created"; //$NON-NLS-1$
+
+  public static final String ATTRIBUTES_REVISED = "cdo_revised"; //$NON-NLS-1$
+
+  public static final String ATTRIBUTES_RESOURCE = "cdo_resource"; //$NON-NLS-1$
+
+  public static final String ATTRIBUTES_CONTAINER = "cdo_container"; //$NON-NLS-1$
+
+  public static final String ATTRIBUTES_FEATURE = "cdo_feature"; //$NON-NLS-1$
+
+  /**
+   * Field names of list tables
+   */
+  public static final String LIST_FEATURE = "cdo_feature"; //$NON-NLS-1$
+
+  public static final String LIST_REVISION_ID = "cdo_source"; //$NON-NLS-1$
+
+  public static final String LIST_REVISION_VERSION = "cdo_version"; //$NON-NLS-1$
+
+  public static final String LIST_REVISION_VERSION_ADDED = "cdo_version_added"; //$NON-NLS-1$
+
+  public static final String LIST_REVISION_VERSION_REMOVED = "cdo_version_removed"; //$NON-NLS-1$
+
+  public static final String LIST_REVISION_BRANCH = "cdo_branch"; //$NON-NLS-1$
+
+  public static final String LIST_IDX = "cdo_idx"; //$NON-NLS-1$
+
+  public static final String LIST_VALUE = "cdo_value"; //$NON-NLS-1$
+
+  /**
+   * Field names of featuremap tables
+   */
+  public static final String FEATUREMAP_REVISION_ID = "cdo_id"; //$NON-NLS-1$
+
+  public static final String FEATUREMAP_VERSION = "cdo_version"; //$NON-NLS-1$
+
+  public static final String FEATUREMAP_VERSION_ADDED = "cdo_version_added"; //$NON-NLS-1$
+
+  public static final String FEATUREMAP_VERSION_REMOVED = "cdo_version_removed"; //$NON-NLS-1$
+
+  public static final String FEATUREMAP_BRANCH = "cdo_branch"; //$NON-NLS-1$
+
+  public static final String FEATUREMAP_IDX = "cdo_idx"; //$NON-NLS-1$
+
+  public static final String FEATUREMAP_TAG = "cdo_tag"; //$NON-NLS-1$
+
+  public static final String FEATUREMAP_VALUE = "cdo_value"; //$NON-NLS-1$
+
+  private CDODBSchema()
+  {
+    super("CDO"); //$NON-NLS-1$
+  }
+
+  static
+  {
+    INSTANCE.lock();
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBAnnotation.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBAnnotation.java
new file mode 100644
index 0000000..1481156
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBAnnotation.java
@@ -0,0 +1,67 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kai Schlamp - initial API and implementation
+ *    Eike Stepper - maintenance
+ *    Kai Schlamp - Bug 284680 - [DB] Provide annotation to bypass ClassMapping
+ *    Stefan Winkler - maintenance
+ *    Stefan Winkler - Bug 285426: [DB] Implement user-defined typeMapping support
+ */
+package org.eclipse.emf.cdo.server.internal.db;
+
+import org.eclipse.emf.ecore.EModelElement;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+
+/**
+ * @author Kai Schlamp
+ */
+public enum DBAnnotation
+{
+  TABLE_MAPPING("tableMapping"), //
+  TABLE_NAME("tableName"), //
+  COLUMN_NAME("columnName"), //
+  COLUMN_TYPE("columnType"), //
+  COLUMN_LENGTH("columnLength"), //
+  TYPE_MAPPING("typeMapping");
+
+  public final static String SOURCE_URI = "http://www.eclipse.org/CDO/DBStore";
+
+  public final static String TABLE_MAPPING_NONE = "NONE";
+
+  private String keyword;
+
+  private DBAnnotation(String keyword)
+  {
+    this.keyword = keyword;
+  }
+
+  public String getKeyword()
+  {
+    return keyword == null ? super.toString() : keyword;
+  }
+
+  /**
+   * @return A non-empty string or <code>null</code>.
+   */
+  public String getValue(EModelElement element)
+  {
+    String value = EcoreUtil.getAnnotation(element, SOURCE_URI, keyword);
+    if (value != null && value.length() == 0)
+    {
+      return null;
+    }
+
+    return value;
+  }
+
+  @Override
+  public String toString()
+  {
+    return getKeyword();
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBBrowserPage.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBBrowserPage.java
new file mode 100644
index 0000000..c81aafe
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBBrowserPage.java
@@ -0,0 +1,208 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server.internal.db;
+
+import org.eclipse.emf.cdo.server.CDOServerBrowser;
+import org.eclipse.emf.cdo.server.CDOServerBrowser.AbstractPage;
+import org.eclipse.emf.cdo.spi.server.InternalRepository;
+
+import org.eclipse.net4j.db.DBException;
+import org.eclipse.net4j.db.DBUtil;
+import org.eclipse.net4j.db.IDBConnectionProvider;
+import org.eclipse.net4j.util.factory.ProductCreationException;
+
+import java.io.PrintStream;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.List;
+
+/**
+ * @author Eike Stepper
+ * @since 4.0
+ */
+public class DBBrowserPage extends AbstractPage
+{
+  public DBBrowserPage()
+  {
+    super("tables", "Database Tables");
+  }
+
+  public boolean canDisplay(InternalRepository repository)
+  {
+    return repository.getStore() instanceof IDBConnectionProvider;
+  }
+
+  public void display(CDOServerBrowser browser, InternalRepository repository, PrintStream out)
+  {
+    IDBConnectionProvider connectionProvider = (IDBConnectionProvider)repository.getStore();
+    Connection connection = null;
+
+    try
+    {
+      connection = connectionProvider.getConnection();
+
+      out.print("<table border=\"0\">\r\n");
+      out.print("<tr>\r\n");
+
+      out.print("<td valign=\"top\">\r\n");
+      String table = showTables(browser, out, connection, repository.getName());
+      out.print("</td>\r\n");
+
+      if (table != null)
+      {
+        out.print("<td valign=\"top\">\r\n");
+        showTable(browser, out, connection, table);
+        out.print("</td>\r\n");
+      }
+
+      out.print("</tr>\r\n");
+      out.print("</table>\r\n");
+    }
+    catch (DBException ex)
+    {
+      ex.printStackTrace();
+    }
+    finally
+    {
+      DBUtil.close(connection);
+    }
+  }
+
+  /**
+   * @since 4.0
+   */
+  protected String showTables(CDOServerBrowser browser, PrintStream pout, Connection connection, String repo)
+  {
+    String table = browser.getParam("table");
+
+    List<String> allTableNames = DBUtil.getAllTableNames(connection, repo);
+    for (String tableName : allTableNames)
+    {
+      if (table == null)
+      {
+        table = tableName;
+      }
+
+      String label = browser.escape(tableName)/* .toLowerCase() */;
+      if (tableName.equals(table))
+      {
+        pout.print("<b>" + label + "</b><br>\r\n");
+      }
+      else
+      {
+        pout.print(browser.href(label, getName(), "table", tableName, "order", null, "direction", null) + "<br>\r\n");
+      }
+    }
+
+    return table;
+  }
+
+  /**
+   * @since 4.0
+   */
+  protected void showTable(CDOServerBrowser browser, PrintStream pout, Connection connection, String table)
+  {
+    try
+    {
+      String order = browser.getParam("order");
+      executeQuery(browser, pout, connection, "SELECT * FROM " + table
+          + (order == null ? "" : " ORDER BY " + order + " " + browser.getParam("direction")));
+    }
+    catch (Exception ex)
+    {
+      browser.removeParam("order");
+      browser.removeParam("direction");
+      executeQuery(browser, pout, connection, "SELECT * FROM " + table);
+    }
+  }
+
+  protected void executeQuery(CDOServerBrowser browser, PrintStream pout, Connection connection, String sql)
+  {
+    String order = browser.getParam("order");
+    String direction = browser.getParam("direction");
+    String highlight = browser.getParam("highlight");
+
+    Statement stmt = null;
+    ResultSet resultSet = null;
+
+    try
+    {
+      stmt = connection.createStatement();
+      resultSet = stmt.executeQuery(sql);
+
+      ResultSetMetaData metaData = resultSet.getMetaData();
+      int columns = metaData.getColumnCount();
+
+      pout.print("<table border=\"1\" cellpadding=\"2\">\r\n");
+      pout.print("<tr>\r\n");
+      pout.print("<td>&nbsp;</td>\r\n");
+      for (int i = 0; i < columns; i++)
+      {
+        String column = metaData.getColumnLabel(1 + i);
+        String type = metaData.getColumnTypeName(1 + i).toLowerCase();
+
+        String dir = column.equals(order) && "ASC".equals(direction) ? "DESC" : "ASC";
+        pout.print("<td align=\"center\"><b>" + browser.href(column, getName(), "order", column, "direction", dir));
+        pout.print("</b><br>" + type + "</td>\r\n");
+      }
+
+      pout.print("</tr>\r\n");
+
+      int row = 0;
+      while (resultSet.next())
+      {
+        ++row;
+        pout.print("<tr>\r\n");
+        pout.print("<td><b>" + row + "</b></td>\r\n");
+        for (int i = 0; i < columns; i++)
+        {
+          String value = resultSet.getString(1 + i);
+          String bgcolor = highlight != null && highlight.equals(value) ? " bgcolor=\"#fffca6\"" : "";
+          pout.print("<td" + bgcolor + ">" + browser.href(value, getName(), "highlight", value) + "</td>\r\n");
+        }
+
+        pout.print("</tr>\r\n");
+      }
+
+      pout.print("</table>\r\n");
+    }
+    catch (SQLException ex)
+    {
+      ex.printStackTrace();
+    }
+    finally
+    {
+      DBUtil.close(resultSet);
+      DBUtil.close(stmt);
+    }
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  public static class Factory extends org.eclipse.net4j.util.factory.Factory
+  {
+    public static final String TYPE = "default";
+
+    public Factory()
+    {
+      super(PRODUCT_GROUP, TYPE);
+    }
+
+    public DBBrowserPage create(String description) throws ProductCreationException
+    {
+      return new DBBrowserPage();
+    }
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBRevisionHandler.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBRevisionHandler.java
new file mode 100644
index 0000000..d47db43
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBRevisionHandler.java
@@ -0,0 +1,40 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server.internal.db;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranchVersion;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionHandler;
+import org.eclipse.emf.cdo.spi.common.revision.DetachedCDORevision;
+
+/**
+ * @author Eike Stepper
+ */
+public class DBRevisionHandler implements CDORevisionHandler
+{
+  private CDORevisionHandler delegate;
+
+  public DBRevisionHandler(CDORevisionHandler delegate)
+  {
+    this.delegate = delegate;
+  }
+
+  public boolean handleRevision(CDORevision revision)
+  {
+    if (revision.getVersion() < CDOBranchVersion.FIRST_VERSION - 1)
+    {
+      revision = new DetachedCDORevision(revision.getEClass(), revision.getID(), revision.getBranch(),
+          -revision.getVersion(), revision.getTimeStamp(), revision.getRevised());
+    }
+
+    return delegate.handleRevision(revision);
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStore.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStore.java
new file mode 100644
index 0000000..3917333
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStore.java
@@ -0,0 +1,727 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - Bug 259402
+ *    Stefan Winkler - Bug 271444: [DB] Multiple refactorings bug 271444
+ *    Stefan Winkler - Bug 249610: [DB] Support external references (Implementation)
+ *    Stefan Winkler - Bug 289056: [DB] Exception "ERROR: relation "cdo_external_refs" does not exist" while executing test-suite for PostgreSQL
+ */
+package org.eclipse.emf.cdo.server.internal.db;
+
+import org.eclipse.emf.cdo.common.CDOCommonRepository.IDGenerationLocation;
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.revision.CDOAllRevisionsProvider;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionHandler;
+import org.eclipse.emf.cdo.server.ISession;
+import org.eclipse.emf.cdo.server.ITransaction;
+import org.eclipse.emf.cdo.server.IView;
+import org.eclipse.emf.cdo.server.StoreThreadLocal;
+import org.eclipse.emf.cdo.server.db.IDBStore;
+import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
+import org.eclipse.emf.cdo.server.db.IIDHandler;
+import org.eclipse.emf.cdo.server.db.IMetaDataManager;
+import org.eclipse.emf.cdo.server.db.mapping.IMappingStrategy;
+import org.eclipse.emf.cdo.server.internal.db.bundle.OM;
+import org.eclipse.emf.cdo.server.internal.db.messages.Messages;
+import org.eclipse.emf.cdo.spi.server.InternalRepository;
+import org.eclipse.emf.cdo.spi.server.LongIDStoreAccessor;
+import org.eclipse.emf.cdo.spi.server.Store;
+import org.eclipse.emf.cdo.spi.server.StoreAccessorPool;
+
+import org.eclipse.net4j.db.DBException;
+import org.eclipse.net4j.db.DBUtil;
+import org.eclipse.net4j.db.IDBAdapter;
+import org.eclipse.net4j.db.IDBConnectionProvider;
+import org.eclipse.net4j.db.ddl.IDBSchema;
+import org.eclipse.net4j.db.ddl.IDBTable;
+import org.eclipse.net4j.spi.db.DBSchema;
+import org.eclipse.net4j.util.ReflectUtil.ExcludeFromDump;
+import org.eclipse.net4j.util.lifecycle.LifecycleUtil;
+import org.eclipse.net4j.util.om.monitor.ProgressDistributor;
+
+import javax.sql.DataSource;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.Timer;
+
+/**
+ * @author Eike Stepper
+ */
+public class DBStore extends Store implements IDBStore, CDOAllRevisionsProvider
+{
+  public static final String TYPE = "db"; //$NON-NLS-1$
+
+  private static final String PROP_REPOSITORY_CREATED = "org.eclipse.emf.cdo.server.db.repositoryCreated"; //$NON-NLS-1$
+
+  private static final String PROP_REPOSITORY_STOPPED = "org.eclipse.emf.cdo.server.db.repositoryStopped"; //$NON-NLS-1$
+
+  private static final String PROP_NEXT_LOCAL_CDOID = "org.eclipse.emf.cdo.server.db.nextLocalCDOID"; //$NON-NLS-1$
+
+  private static final String PROP_LAST_CDOID = "org.eclipse.emf.cdo.server.db.lastCDOID"; //$NON-NLS-1$
+
+  private static final String PROP_LAST_BRANCHID = "org.eclipse.emf.cdo.server.db.lastBranchID"; //$NON-NLS-1$
+
+  private static final String PROP_LAST_LOCAL_BRANCHID = "org.eclipse.emf.cdo.server.db.lastLocalBranchID"; //$NON-NLS-1$
+
+  private static final String PROP_LAST_COMMITTIME = "org.eclipse.emf.cdo.server.db.lastCommitTime"; //$NON-NLS-1$
+
+  private static final String PROP_LAST_NONLOCAL_COMMITTIME = "org.eclipse.emf.cdo.server.db.lastNonLocalCommitTime"; //$NON-NLS-1$
+
+  private static final String PROP_GRACEFULLY_SHUT_DOWN = "org.eclipse.emf.cdo.server.db.gracefullyShutDown"; //$NON-NLS-1$
+
+  private long creationTime;
+
+  private boolean firstTime;
+
+  private Map<String, String> properties;
+
+  private IIDHandler idHandler;
+
+  private IMetaDataManager metaDataManager = new MetaDataManager(this);
+
+  private DurableLockingManager durableLockingManager = new DurableLockingManager(this);
+
+  private IMappingStrategy mappingStrategy;
+
+  private IDBSchema dbSchema;
+
+  private IDBAdapter dbAdapter;
+
+  private IDBConnectionProvider dbConnectionProvider;
+
+  @ExcludeFromDump
+  private transient ProgressDistributor accessorWriteDistributor = new ProgressDistributor.Geometric()
+  {
+    @Override
+    public String toString()
+    {
+      String result = "accessorWriteDistributor"; //$NON-NLS-1$
+      if (getRepository() != null)
+      {
+        result += ": " + getRepository().getName(); //$NON-NLS-1$
+      }
+
+      return result;
+    }
+  };
+
+  @ExcludeFromDump
+  private transient StoreAccessorPool readerPool = new StoreAccessorPool(this, null);
+
+  @ExcludeFromDump
+  private transient StoreAccessorPool writerPool = new StoreAccessorPool(this, null);
+
+  @ExcludeFromDump
+  private transient Timer connectionKeepAliveTimer;
+
+  public DBStore()
+  {
+    super(TYPE, null, set(ChangeFormat.REVISION, ChangeFormat.DELTA), //
+        set(RevisionTemporality.AUDITING, RevisionTemporality.NONE), //
+        set(RevisionParallelism.NONE, RevisionParallelism.BRANCHING));
+  }
+
+  public IMappingStrategy getMappingStrategy()
+  {
+    return mappingStrategy;
+  }
+
+  public void setMappingStrategy(IMappingStrategy mappingStrategy)
+  {
+    this.mappingStrategy = mappingStrategy;
+    mappingStrategy.setStore(this);
+  }
+
+  public IDBAdapter getDBAdapter()
+  {
+    return dbAdapter;
+  }
+
+  public void setDBAdapter(IDBAdapter dbAdapter)
+  {
+    this.dbAdapter = dbAdapter;
+  }
+
+  public void setProperties(Map<String, String> properties)
+  {
+    this.properties = properties;
+  }
+
+  public Map<String, String> getProperties()
+  {
+    return properties;
+  }
+
+  public IIDHandler getIDHandler()
+  {
+    return idHandler;
+  }
+
+  public Connection getConnection()
+  {
+    Connection connection = dbConnectionProvider.getConnection();
+    if (connection == null)
+    {
+      throw new DBException("No connection from connection provider: " + dbConnectionProvider); //$NON-NLS-1$
+    }
+
+    try
+    {
+      connection.setAutoCommit(false);
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex, "SET AUTO COMMIT = false");
+    }
+
+    return connection;
+  }
+
+  public void setDbConnectionProvider(IDBConnectionProvider dbConnectionProvider)
+  {
+    this.dbConnectionProvider = dbConnectionProvider;
+  }
+
+  public void setDataSource(DataSource dataSource)
+  {
+    dbConnectionProvider = DBUtil.createConnectionProvider(dataSource);
+  }
+
+  public IMetaDataManager getMetaDataManager()
+  {
+    return metaDataManager;
+  }
+
+  public DurableLockingManager getDurableLockingManager()
+  {
+    return durableLockingManager;
+  }
+
+  public Timer getConnectionKeepAliveTimer()
+  {
+    return connectionKeepAliveTimer;
+  }
+
+  @Override
+  public Set<ChangeFormat> getSupportedChangeFormats()
+  {
+    if (mappingStrategy.hasDeltaSupport())
+    {
+      return set(ChangeFormat.DELTA);
+    }
+
+    return set(ChangeFormat.REVISION);
+  }
+
+  public ProgressDistributor getAccessorWriteDistributor()
+  {
+    return accessorWriteDistributor;
+  }
+
+  public IDBSchema getDBSchema()
+  {
+    return dbSchema;
+  }
+
+  public Map<String, String> getPersistentProperties(Set<String> names)
+  {
+    Connection connection = null;
+    PreparedStatement selectStmt = null;
+    String sql = null;
+
+    try
+    {
+      connection = getConnection();
+      Map<String, String> result = new HashMap<String, String>();
+      boolean allProperties = names == null || names.isEmpty();
+      if (allProperties)
+      {
+        sql = CDODBSchema.SQL_SELECT_ALL_PROPERTIES;
+        selectStmt = connection.prepareStatement(sql);
+        ResultSet resultSet = null;
+
+        try
+        {
+          resultSet = selectStmt.executeQuery();
+          while (resultSet.next())
+          {
+            String key = resultSet.getString(1);
+            String value = resultSet.getString(2);
+            result.put(key, value);
+          }
+        }
+        finally
+        {
+          DBUtil.close(resultSet);
+        }
+      }
+      else
+      {
+        sql = CDODBSchema.SQL_SELECT_PROPERTIES;
+        selectStmt = connection.prepareStatement(sql);
+        for (String name : names)
+        {
+          selectStmt.setString(1, name);
+          ResultSet resultSet = null;
+
+          try
+          {
+            resultSet = selectStmt.executeQuery();
+            if (resultSet.next())
+            {
+              String value = resultSet.getString(1);
+              result.put(name, value);
+            }
+          }
+          finally
+          {
+            DBUtil.close(resultSet);
+          }
+        }
+      }
+
+      return result;
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex, sql);
+    }
+    finally
+    {
+      DBUtil.close(selectStmt);
+      DBUtil.close(connection);
+    }
+  }
+
+  public void setPersistentProperties(Map<String, String> properties)
+  {
+    Connection connection = null;
+    PreparedStatement deleteStmt = null;
+    PreparedStatement insertStmt = null;
+    String sql = null;
+
+    try
+    {
+      connection = getConnection();
+      deleteStmt = connection.prepareStatement(CDODBSchema.SQL_DELETE_PROPERTIES);
+      insertStmt = connection.prepareStatement(CDODBSchema.SQL_INSERT_PROPERTIES);
+
+      for (Entry<String, String> entry : properties.entrySet())
+      {
+        String name = entry.getKey();
+        String value = entry.getValue();
+
+        sql = CDODBSchema.SQL_DELETE_PROPERTIES;
+        deleteStmt.setString(1, name);
+        deleteStmt.executeUpdate();
+
+        sql = CDODBSchema.SQL_INSERT_PROPERTIES;
+        insertStmt.setString(1, name);
+        insertStmt.setString(2, value);
+        insertStmt.executeUpdate();
+      }
+
+      sql = null;
+      connection.commit();
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex, sql);
+    }
+    finally
+    {
+      DBUtil.close(insertStmt);
+      DBUtil.close(deleteStmt);
+      DBUtil.close(connection);
+    }
+  }
+
+  public void removePersistentProperties(Set<String> names)
+  {
+    Connection connection = null;
+    PreparedStatement deleteStmt = null;
+
+    try
+    {
+      connection = getConnection();
+      deleteStmt = connection.prepareStatement(CDODBSchema.SQL_DELETE_PROPERTIES);
+
+      for (String name : names)
+      {
+        deleteStmt.setString(1, name);
+        deleteStmt.executeUpdate();
+      }
+
+      connection.commit();
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex, CDODBSchema.SQL_DELETE_PROPERTIES);
+    }
+    finally
+    {
+      DBUtil.close(deleteStmt);
+      DBUtil.close(connection);
+    }
+  }
+
+  @Override
+  public DBStoreAccessor getReader(ISession session)
+  {
+    return (DBStoreAccessor)super.getReader(session);
+  }
+
+  @Override
+  public DBStoreAccessor getWriter(ITransaction transaction)
+  {
+    return (DBStoreAccessor)super.getWriter(transaction);
+  }
+
+  @Override
+  protected StoreAccessorPool getReaderPool(ISession session, boolean forReleasing)
+  {
+    return readerPool;
+  }
+
+  @Override
+  protected StoreAccessorPool getWriterPool(IView view, boolean forReleasing)
+  {
+    return writerPool;
+  }
+
+  @Override
+  protected DBStoreAccessor createReader(ISession session) throws DBException
+  {
+    return new DBStoreAccessor(this, session);
+  }
+
+  @Override
+  protected DBStoreAccessor createWriter(ITransaction transaction) throws DBException
+  {
+    return new DBStoreAccessor(this, transaction);
+  }
+
+  public Map<CDOBranch, List<CDORevision>> getAllRevisions()
+  {
+    final Map<CDOBranch, List<CDORevision>> result = new HashMap<CDOBranch, List<CDORevision>>();
+    IDBStoreAccessor accessor = getReader(null);
+    StoreThreadLocal.setAccessor(accessor);
+
+    try
+    {
+      accessor.handleRevisions(null, null, CDOBranchPoint.UNSPECIFIED_DATE, true,
+          new CDORevisionHandler.Filtered.Undetached(new CDORevisionHandler()
+          {
+            public boolean handleRevision(CDORevision revision)
+            {
+              CDOBranch branch = revision.getBranch();
+              List<CDORevision> list = result.get(branch);
+              if (list == null)
+              {
+                list = new ArrayList<CDORevision>();
+                result.put(branch, list);
+              }
+
+              list.add(revision);
+              return true;
+            }
+          }));
+    }
+    finally
+    {
+      StoreThreadLocal.release();
+    }
+
+    return result;
+  }
+
+  public CDOID createObjectID(String val)
+  {
+    return idHandler.createCDOID(val);
+  }
+
+  public boolean isLocal(CDOID id)
+  {
+    return idHandler.isLocalCDOID(id);
+  }
+
+  public CDOID getNextCDOID(LongIDStoreAccessor accessor, CDORevision revision)
+  {
+    return idHandler.getNextCDOID(revision);
+  }
+
+  public long getCreationTime()
+  {
+    return creationTime;
+  }
+
+  public void setCreationTime(long creationTime)
+  {
+    this.creationTime = creationTime;
+
+    Map<String, String> map = new HashMap<String, String>();
+    map.put(PROP_REPOSITORY_CREATED, Long.toString(creationTime));
+    setPersistentProperties(map);
+  }
+
+  public boolean isFirstStart()
+  {
+    return firstTime;
+  }
+
+  @Override
+  protected void doBeforeActivate() throws Exception
+  {
+    super.doBeforeActivate();
+    checkNull(mappingStrategy, Messages.getString("DBStore.2")); //$NON-NLS-1$
+    checkNull(dbAdapter, Messages.getString("DBStore.1")); //$NON-NLS-1$
+    checkNull(dbConnectionProvider, Messages.getString("DBStore.0")); //$NON-NLS-1$
+  }
+
+  @Override
+  protected void doActivate() throws Exception
+  {
+    super.doActivate();
+
+    if (getRepository().getIDGenerationLocation() == IDGenerationLocation.CLIENT)
+    {
+      idHandler = new UUIDHandler(this);
+    }
+    else
+    {
+      idHandler = new LongIDHandler(this);
+    }
+
+    setObjectIDTypes(idHandler.getObjectIDTypes());
+    connectionKeepAliveTimer = new Timer("Connection-Keep-Alive-" + this); //$NON-NLS-1$
+
+    Set<IDBTable> createdTables = null;
+    Connection connection = getConnection();
+
+    try
+    {
+      if (isDropAllDataOnActivate())
+      {
+        OM.LOG.info("Dropping all tables from repository " + getRepository().getName() + "...");
+        DBUtil.dropAllTables(connection, null);
+        connection.commit();
+      }
+
+      createdTables = CDODBSchema.INSTANCE.create(dbAdapter, connection);
+      connection.commit();
+    }
+    finally
+    {
+      DBUtil.close(connection);
+    }
+
+    dbSchema = createSchema();
+
+    LifecycleUtil.activate(idHandler);
+    LifecycleUtil.activate(metaDataManager);
+    LifecycleUtil.activate(durableLockingManager);
+    LifecycleUtil.activate(mappingStrategy);
+
+    setRevisionTemporality(mappingStrategy.hasAuditSupport() ? RevisionTemporality.AUDITING : RevisionTemporality.NONE);
+    setRevisionParallelism(mappingStrategy.hasBranchingSupport() ? RevisionParallelism.BRANCHING
+        : RevisionParallelism.NONE);
+
+    if (isFirstStart(createdTables))
+    {
+      firstStart();
+    }
+    else
+    {
+      reStart();
+    }
+  }
+
+  @Override
+  protected void doDeactivate() throws Exception
+  {
+    LifecycleUtil.deactivate(mappingStrategy);
+    LifecycleUtil.deactivate(durableLockingManager);
+    LifecycleUtil.deactivate(metaDataManager);
+    LifecycleUtil.deactivate(idHandler);
+
+    Map<String, String> map = new HashMap<String, String>();
+    map.put(PROP_GRACEFULLY_SHUT_DOWN, Boolean.TRUE.toString());
+    map.put(PROP_REPOSITORY_STOPPED, Long.toString(getRepository().getTimeStamp()));
+
+    if (getRepository().getIDGenerationLocation() == IDGenerationLocation.STORE)
+    {
+      map.put(PROP_NEXT_LOCAL_CDOID, Store.idToString(idHandler.getNextLocalObjectID()));
+      map.put(PROP_LAST_CDOID, Store.idToString(idHandler.getLastObjectID()));
+    }
+
+    map.put(PROP_LAST_BRANCHID, Integer.toString(getLastBranchID()));
+    map.put(PROP_LAST_LOCAL_BRANCHID, Integer.toString(getLastLocalBranchID()));
+    map.put(PROP_LAST_COMMITTIME, Long.toString(getLastCommitTime()));
+    map.put(PROP_LAST_NONLOCAL_COMMITTIME, Long.toString(getLastNonLocalCommitTime()));
+    setPersistentProperties(map);
+
+    if (readerPool != null)
+    {
+      readerPool.dispose();
+    }
+
+    if (writerPool != null)
+    {
+      writerPool.dispose();
+    }
+
+    connectionKeepAliveTimer.cancel();
+    connectionKeepAliveTimer = null;
+
+    super.doDeactivate();
+  }
+
+  protected boolean isFirstStart(Set<IDBTable> createdTables)
+  {
+    if (createdTables.contains(CDODBSchema.PROPERTIES))
+    {
+      return true;
+    }
+
+    Set<String> names = new HashSet<String>();
+    names.add(PROP_REPOSITORY_CREATED);
+
+    Map<String, String> map = getPersistentProperties(names);
+    return map.get(PROP_REPOSITORY_CREATED) == null;
+  }
+
+  protected void firstStart()
+  {
+    InternalRepository repository = getRepository();
+    setCreationTime(repository.getTimeStamp());
+    firstTime = true;
+  }
+
+  protected void reStart()
+  {
+    Set<String> names = new HashSet<String>();
+    names.add(PROP_REPOSITORY_CREATED);
+    names.add(PROP_GRACEFULLY_SHUT_DOWN);
+
+    Map<String, String> map = getPersistentProperties(names);
+    creationTime = Long.valueOf(map.get(PROP_REPOSITORY_CREATED));
+
+    if (map.containsKey(PROP_GRACEFULLY_SHUT_DOWN))
+    {
+      names.clear();
+
+      InternalRepository repository = getRepository();
+      boolean generatingIDs = repository.getIDGenerationLocation() == IDGenerationLocation.STORE;
+      if (generatingIDs)
+      {
+        names.add(PROP_NEXT_LOCAL_CDOID);
+        names.add(PROP_LAST_CDOID);
+      }
+
+      names.add(PROP_LAST_BRANCHID);
+      names.add(PROP_LAST_LOCAL_BRANCHID);
+      names.add(PROP_LAST_COMMITTIME);
+      names.add(PROP_LAST_NONLOCAL_COMMITTIME);
+      map = getPersistentProperties(names);
+
+      if (generatingIDs)
+      {
+        idHandler.setNextLocalObjectID(Store.stringToID(map.get(PROP_NEXT_LOCAL_CDOID)));
+        idHandler.setLastObjectID(Store.stringToID(map.get(PROP_LAST_CDOID)));
+      }
+
+      setLastBranchID(Integer.valueOf(map.get(PROP_LAST_BRANCHID)));
+      setLastLocalBranchID(Integer.valueOf(map.get(PROP_LAST_LOCAL_BRANCHID)));
+      setLastCommitTime(Long.valueOf(map.get(PROP_LAST_COMMITTIME)));
+      setLastNonLocalCommitTime(Long.valueOf(map.get(PROP_LAST_NONLOCAL_COMMITTIME)));
+    }
+    else
+    {
+      repairAfterCrash();
+    }
+
+    removePersistentProperties(Collections.singleton(PROP_GRACEFULLY_SHUT_DOWN));
+  }
+
+  protected void repairAfterCrash()
+  {
+    String name = getRepository().getName();
+    OM.LOG.warn(MessageFormat.format(Messages.getString("DBStore.9"), name)); //$NON-NLS-1$
+
+    Connection connection = getConnection();
+
+    try
+    {
+      connection.setAutoCommit(false);
+      connection.setReadOnly(true);
+
+      mappingStrategy.repairAfterCrash(dbAdapter, connection); // Must update the idHandler
+
+      boolean storeIDs = getRepository().getIDGenerationLocation() == IDGenerationLocation.STORE;
+      CDOID lastObjectID = storeIDs ? idHandler.getLastObjectID() : CDOID.NULL;
+      CDOID nextLocalObjectID = storeIDs ? idHandler.getNextLocalObjectID() : CDOID.NULL;
+
+      int branchID = DBUtil.selectMaximumInt(connection, CDODBSchema.BRANCHES_ID);
+      setLastBranchID(branchID > 0 ? branchID : 0);
+
+      int localBranchID = DBUtil.selectMinimumInt(connection, CDODBSchema.BRANCHES_ID);
+      setLastLocalBranchID(localBranchID < 0 ? localBranchID : 0);
+
+      long lastCommitTime = DBUtil.selectMaximumLong(connection, CDODBSchema.COMMIT_INFOS_TIMESTAMP);
+      setLastCommitTime(lastCommitTime);
+
+      long lastNonLocalCommitTime = DBUtil.selectMaximumLong(connection, CDODBSchema.COMMIT_INFOS_TIMESTAMP,
+          CDOBranch.MAIN_BRANCH_ID + "<=" + CDODBSchema.COMMIT_INFOS_BRANCH);
+      setLastNonLocalCommitTime(lastNonLocalCommitTime);
+
+      if (storeIDs)
+      {
+        OM.LOG
+            .info(MessageFormat.format(
+                Messages.getString("DBStore.10"), name, lastObjectID, nextLocalObjectID, getLastBranchID(), getLastCommitTime(), getLastNonLocalCommitTime())); //$NON-NLS-1$
+      }
+      else
+      {
+        OM.LOG
+            .info(MessageFormat.format(
+                Messages.getString("DBStore.10b"), name, getLastBranchID(), getLastCommitTime(), getLastNonLocalCommitTime())); //$NON-NLS-1$
+      }
+    }
+    catch (SQLException e)
+    {
+      OM.LOG.error(MessageFormat.format(Messages.getString("DBStore.11"), name), e); //$NON-NLS-1$
+      throw new DBException(e);
+    }
+    finally
+    {
+      DBUtil.close(connection);
+    }
+  }
+
+  protected IDBSchema createSchema()
+  {
+    String name = getRepository().getName();
+    return new DBSchema(name);
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStoreAccessor.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStoreAccessor.java
new file mode 100644
index 0000000..42aca92
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStoreAccessor.java
@@ -0,0 +1,1393 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - bug 259402
+ *    Stefan Winkler - 271444: [DB] Multiple refactorings bug 271444
+ *    Andre Dietisheim - bug 256649
+ *    Caspar De Groot - maintenance
+ */
+package org.eclipse.emf.cdo.server.internal.db;
+
+import org.eclipse.emf.cdo.common.CDOCommonRepository.IDGenerationLocation;
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchHandler;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.branch.CDOBranchVersion;
+import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
+import org.eclipse.emf.cdo.common.commit.CDOCommitInfoHandler;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.lob.CDOLobHandler;
+import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockArea.Handler;
+import org.eclipse.emf.cdo.common.model.CDOClassifierRef;
+import org.eclipse.emf.cdo.common.model.CDOPackageRegistry;
+import org.eclipse.emf.cdo.common.protocol.CDODataInput;
+import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionCacheAdder;
+import org.eclipse.emf.cdo.common.revision.CDORevisionHandler;
+import org.eclipse.emf.cdo.common.util.CDOQueryInfo;
+import org.eclipse.emf.cdo.eresource.EresourcePackage;
+import org.eclipse.emf.cdo.server.IQueryHandler;
+import org.eclipse.emf.cdo.server.IRepository;
+import org.eclipse.emf.cdo.server.ISession;
+import org.eclipse.emf.cdo.server.IStoreAccessor;
+import org.eclipse.emf.cdo.server.IStoreAccessor.DurableLocking2;
+import org.eclipse.emf.cdo.server.ITransaction;
+import org.eclipse.emf.cdo.server.db.CDODBUtil;
+import org.eclipse.emf.cdo.server.db.IDBStore;
+import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
+import org.eclipse.emf.cdo.server.db.IIDHandler;
+import org.eclipse.emf.cdo.server.db.IMetaDataManager;
+import org.eclipse.emf.cdo.server.db.IPreparedStatementCache;
+import org.eclipse.emf.cdo.server.db.IPreparedStatementCache.ReuseProbability;
+import org.eclipse.emf.cdo.server.db.mapping.IClassMapping;
+import org.eclipse.emf.cdo.server.db.mapping.IClassMappingAuditSupport;
+import org.eclipse.emf.cdo.server.db.mapping.IClassMappingDeltaSupport;
+import org.eclipse.emf.cdo.server.db.mapping.IMappingStrategy;
+import org.eclipse.emf.cdo.server.internal.db.bundle.OM;
+import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranch;
+import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranchManager;
+import org.eclipse.emf.cdo.spi.common.commit.CDOChangeSetSegment;
+import org.eclipse.emf.cdo.spi.common.commit.InternalCDOCommitInfoManager;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit;
+import org.eclipse.emf.cdo.spi.common.revision.DetachedCDORevision;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionDelta;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager;
+import org.eclipse.emf.cdo.spi.server.InternalCommitContext;
+import org.eclipse.emf.cdo.spi.server.InternalRepository;
+import org.eclipse.emf.cdo.spi.server.StoreAccessor;
+
+import org.eclipse.net4j.db.DBException;
+import org.eclipse.net4j.db.DBUtil;
+import org.eclipse.net4j.util.HexUtil;
+import org.eclipse.net4j.util.ObjectUtil;
+import org.eclipse.net4j.util.StringUtil;
+import org.eclipse.net4j.util.collection.CloseableIterator;
+import org.eclipse.net4j.util.collection.Pair;
+import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
+import org.eclipse.net4j.util.io.IOUtil;
+import org.eclipse.net4j.util.lifecycle.LifecycleUtil;
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+import org.eclipse.net4j.util.om.monitor.OMMonitor.Async;
+import org.eclipse.net4j.util.om.trace.ContextTracer;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.Writer;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TimerTask;
+
+/**
+ * @author Eike Stepper
+ */
+public class DBStoreAccessor extends StoreAccessor implements IDBStoreAccessor, DurableLocking2
+{
+  private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG, DBStoreAccessor.class);
+
+  private Connection connection;
+
+  private ConnectionKeepAliveTask connectionKeepAliveTask;
+
+  private IPreparedStatementCache statementCache;
+
+  private Set<CDOID> newObjects = new HashSet<CDOID>();
+
+  private CDOID maxID = CDOID.NULL;
+
+  public DBStoreAccessor(DBStore store, ISession session) throws DBException
+  {
+    super(store, session);
+  }
+
+  public DBStoreAccessor(DBStore store, ITransaction transaction) throws DBException
+  {
+    super(store, transaction);
+  }
+
+  @Override
+  public DBStore getStore()
+  {
+    return (DBStore)super.getStore();
+  }
+
+  public IPreparedStatementCache getStatementCache()
+  {
+    return statementCache;
+  }
+
+  public DBStoreChunkReader createChunkReader(InternalCDORevision revision, EStructuralFeature feature)
+  {
+    return new DBStoreChunkReader(this, revision, feature);
+  }
+
+  /**
+   * Returns an iterator that iterates over all objects in the store and makes their CDOIDs available for processing.
+   * This method is supposed to be called very infrequently, for example during the recovery from a crash.
+   * 
+   * @since 2.0
+   * @deprecated Not used by the framework anymore.
+   */
+  @Deprecated
+  public CloseableIterator<CDOID> readObjectIDs()
+  {
+    if (TRACER.isEnabled())
+    {
+      TRACER.trace("Selecting object IDs"); //$NON-NLS-1$
+    }
+
+    return getStore().getMappingStrategy().readObjectIDs(this);
+  }
+
+  public CDOClassifierRef readObjectType(CDOID id)
+  {
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Selecting object type: {0}", id); //$NON-NLS-1$
+    }
+
+    IMappingStrategy mappingStrategy = getStore().getMappingStrategy();
+    return mappingStrategy.readObjectType(this, id);
+  }
+
+  protected EClass getObjectType(CDOID id)
+  {
+    IRepository repository = getStore().getRepository();
+    if (repository.getRootResourceID().equals(id))
+    {
+      return EresourcePackage.Literals.CDO_RESOURCE;
+    }
+
+    EClass result = repository.getRevisionManager().getObjectType(id);
+    if (result != null)
+    {
+      return result;
+    }
+
+    CDOClassifierRef type = readObjectType(id);
+    if (type != null)
+    {
+      CDOPackageRegistry packageRegistry = repository.getPackageRegistry();
+      return (EClass)type.resolve(packageRegistry);
+    }
+
+    return null;
+  }
+
+  public InternalCDORevision readRevision(CDOID id, CDOBranchPoint branchPoint, int listChunk,
+      CDORevisionCacheAdder cache)
+  {
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Selecting revision {0} from {1}", id, branchPoint); //$NON-NLS-1$
+    }
+
+    IMappingStrategy mappingStrategy = getStore().getMappingStrategy();
+
+    EClass eClass = getObjectType(id);
+    if (eClass != null)
+    {
+      InternalCDORevision revision = getStore().createRevision(eClass, id);
+      revision.setBranchPoint(branchPoint);
+
+      IClassMapping mapping = mappingStrategy.getClassMapping(eClass);
+      if (mapping.readRevision(this, revision, listChunk))
+      {
+        int version = revision.getVersion();
+        if (version < CDOBranchVersion.FIRST_VERSION - 1)
+        {
+          return new DetachedCDORevision(eClass, id, revision.getBranch(), -version, revision.getTimeStamp(),
+              revision.getRevised());
+        }
+
+        return revision;
+      }
+    }
+
+    // Reading failed - revision does not exist.
+    return null;
+  }
+
+  public InternalCDORevision readRevisionByVersion(CDOID id, CDOBranchVersion branchVersion, int listChunk,
+      CDORevisionCacheAdder cache)
+  {
+    DBStore store = getStore();
+    EClass eClass = getObjectType(id);
+
+    IMappingStrategy mappingStrategy = store.getMappingStrategy();
+    IClassMapping mapping = mappingStrategy.getClassMapping(eClass);
+
+    InternalCDORevision revision = store.createRevision(eClass, id);
+    revision.setVersion(branchVersion.getVersion());
+    revision.setBranchPoint(branchVersion.getBranch().getHead());
+
+    boolean success = false;
+
+    if (mappingStrategy.hasAuditSupport())
+    {
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Selecting revision {0} from {1}", id, branchVersion); //$NON-NLS-1$
+      }
+
+      // if audit support is present, just use the audit method
+      success = ((IClassMappingAuditSupport)mapping).readRevisionByVersion(this, revision, listChunk);
+      if (success && revision.getVersion() < CDOBranchVersion.FIRST_VERSION - 1)
+      {
+        // it is detached revision
+        revision = new DetachedCDORevision(eClass, id, revision.getBranch(), -revision.getVersion(),
+            revision.getTimeStamp(), revision.getRevised());
+
+      }
+    }
+    else
+    {
+      // if audit support is not present, we still have to provide a method
+      // to readRevisionByVersion because TransactionCommitContext.computeDirtyObject
+      // needs to lookup the base revision for a change. Hence we emulate this
+      // behavior by getting the current revision and asserting that the version
+      // has not changed. This is valid because if the version has changed,
+      // we are in trouble because of a conflict anyways.
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Selecting current base revision: {0}", id); //$NON-NLS-1$
+      }
+
+      success = mapping.readRevision(this, revision, listChunk);
+
+      if (success && revision.getVersion() != branchVersion.getVersion())
+      {
+        throw new IllegalStateException("Can only retrieve current version " + revision.getVersion() + " for " + id //$NON-NLS-1$ //$NON-NLS-2$
+            + " - version requested was " + branchVersion); //$NON-NLS-1$
+      }
+    }
+
+    return success ? revision : null;
+  }
+
+  /**
+   * @since 2.0
+   */
+  public void queryResources(QueryResourcesContext context)
+  {
+    IMappingStrategy mappingStrategy = getStore().getMappingStrategy();
+    mappingStrategy.queryResources(this, context);
+  }
+
+  public void queryXRefs(QueryXRefsContext context)
+  {
+    IMappingStrategy mappingStrategy = getStore().getMappingStrategy();
+    mappingStrategy.queryXRefs(this, context);
+  }
+
+  public IQueryHandler getQueryHandler(CDOQueryInfo info)
+  {
+    String queryLanguage = info.getQueryLanguage();
+    if (StringUtil.equalsUpperOrLowerCase(queryLanguage, SQLQueryHandler.QUERY_LANGUAGE))
+    {
+      return new SQLQueryHandler(this);
+    }
+
+    return null;
+  }
+
+  public void queryLobs(List<byte[]> ids)
+  {
+    PreparedStatement stmt = null;
+    ResultSet resultSet = null;
+
+    try
+    {
+      stmt = statementCache.getPreparedStatement(CDODBSchema.SQL_QUERY_LOBS, ReuseProbability.MEDIUM);
+
+      for (Iterator<byte[]> it = ids.iterator(); it.hasNext();)
+      {
+        byte[] id = it.next();
+        stmt.setString(1, HexUtil.bytesToHex(id));
+
+        try
+        {
+          resultSet = stmt.executeQuery();
+          if (!resultSet.next())
+          {
+            it.remove();
+          }
+        }
+        finally
+        {
+          DBUtil.close(resultSet);
+        }
+      }
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  public void loadLob(byte[] id, OutputStream out) throws IOException
+  {
+    PreparedStatement stmt = null;
+    ResultSet resultSet = null;
+
+    try
+    {
+      stmt = statementCache.getPreparedStatement(CDODBSchema.SQL_LOAD_LOB, ReuseProbability.MEDIUM);
+      stmt.setString(1, HexUtil.bytesToHex(id));
+
+      try
+      {
+        resultSet = stmt.executeQuery();
+        resultSet.next();
+
+        long size = resultSet.getLong(1);
+        Blob blob = resultSet.getBlob(2);
+        if (resultSet.wasNull())
+        {
+          Clob clob = resultSet.getClob(3);
+          Reader in = clob.getCharacterStream();
+          IOUtil.copyCharacter(in, new OutputStreamWriter(out), size);
+        }
+        else
+        {
+          InputStream in = blob.getBinaryStream();
+          IOUtil.copyBinary(in, out, size);
+        }
+      }
+      finally
+      {
+        DBUtil.close(resultSet);
+      }
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  public void handleLobs(long fromTime, long toTime, CDOLobHandler handler) throws IOException
+  {
+    PreparedStatement stmt = null;
+    ResultSet resultSet = null;
+
+    try
+    {
+      stmt = statementCache.getPreparedStatement(CDODBSchema.SQL_HANDLE_LOBS, ReuseProbability.LOW);
+
+      try
+      {
+        resultSet = stmt.executeQuery();
+        while (resultSet.next())
+        {
+          byte[] id = HexUtil.hexToBytes(resultSet.getString(1));
+          long size = resultSet.getLong(2);
+          Blob blob = resultSet.getBlob(3);
+          if (resultSet.wasNull())
+          {
+            Clob clob = resultSet.getClob(4);
+            Reader in = clob.getCharacterStream();
+            Writer out = handler.handleClob(id, size);
+            if (out != null)
+            {
+              try
+              {
+                IOUtil.copyCharacter(in, out, size);
+              }
+              finally
+              {
+                IOUtil.close(out);
+              }
+            }
+          }
+          else
+          {
+            InputStream in = blob.getBinaryStream();
+            OutputStream out = handler.handleBlob(id, size);
+            if (out != null)
+            {
+              try
+              {
+                IOUtil.copyBinary(in, out, size);
+              }
+              finally
+              {
+                IOUtil.close(out);
+              }
+            }
+          }
+        }
+      }
+      finally
+      {
+        DBUtil.close(resultSet);
+      }
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  @Override
+  protected void applyIDMappings(InternalCommitContext context, OMMonitor monitor)
+  {
+    super.applyIDMappings(context, monitor);
+
+    // Remember maxID because it may have to be adjusted if the repository is BACKUP or CLONE. See bug 325097.
+    boolean adjustMaxID = !context.getBranchPoint().getBranch().isLocal()
+        && getStore().getRepository().getIDGenerationLocation() == IDGenerationLocation.STORE;
+
+    IIDHandler idHandler = getStore().getIDHandler();
+
+    // Remember CDOIDs of new objects. They are cleared after writeRevisions()
+    for (InternalCDORevision revision : context.getNewObjects())
+    {
+      CDOID id = revision.getID();
+      newObjects.add(id);
+
+      if (adjustMaxID && idHandler.compare(id, maxID) > 0)
+      {
+        maxID = id;
+      }
+    }
+  }
+
+  @Override
+  protected void writeCommitInfo(CDOBranch branch, long timeStamp, long previousTimeStamp, String userID,
+      String comment, OMMonitor monitor)
+  {
+    PreparedStatement stmt = null;
+
+    try
+    {
+      stmt = statementCache.getPreparedStatement(CDODBSchema.SQL_CREATE_COMMIT_INFO, ReuseProbability.HIGH);
+      stmt.setLong(1, timeStamp);
+      stmt.setLong(2, previousTimeStamp);
+      stmt.setInt(3, branch.getID());
+      stmt.setString(4, userID);
+      stmt.setString(5, comment);
+
+      DBUtil.update(stmt, true);
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  @Override
+  protected void writeRevisionDeltas(InternalCDORevisionDelta[] revisionDeltas, CDOBranch branch, long created,
+      OMMonitor monitor)
+  {
+    IMappingStrategy mappingStrategy = getStore().getMappingStrategy();
+
+    if (!mappingStrategy.hasDeltaSupport())
+    {
+      throw new UnsupportedOperationException("Mapping strategy does not support revision deltas"); //$NON-NLS-1$
+    }
+
+    monitor.begin(revisionDeltas.length);
+    try
+    {
+      for (InternalCDORevisionDelta delta : revisionDeltas)
+      {
+        writeRevisionDelta(delta, created, monitor.fork());
+      }
+    }
+    finally
+    {
+      monitor.done();
+    }
+  }
+
+  protected void writeRevisionDelta(InternalCDORevisionDelta delta, long created, OMMonitor monitor)
+  {
+    CDOID id = delta.getID();
+    EClass eClass = getObjectType(id);
+    IClassMappingDeltaSupport mapping = (IClassMappingDeltaSupport)getStore().getMappingStrategy().getClassMapping(
+        eClass);
+    mapping.writeRevisionDelta(this, delta, created, monitor);
+  }
+
+  @Override
+  protected void writeRevisions(InternalCDORevision[] revisions, CDOBranch branch, OMMonitor monitor)
+  {
+    try
+    {
+      monitor.begin(revisions.length);
+      for (InternalCDORevision revision : revisions)
+      {
+        writeRevision(revision, newObjects.contains(revision.getID()), true, monitor.fork());
+      }
+    }
+    finally
+    {
+      newObjects.clear();
+      monitor.done();
+    }
+  }
+
+  protected void writeRevision(InternalCDORevision revision, boolean mapType, boolean revise, OMMonitor monitor)
+  {
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Writing revision: {0}", revision); //$NON-NLS-1$
+    }
+
+    EClass eClass = revision.getEClass();
+
+    IClassMapping mapping = getStore().getMappingStrategy().getClassMapping(eClass);
+    mapping.writeRevision(this, revision, mapType, revise, monitor);
+  }
+
+  /*
+   * XXX Eike: change API from CDOID[] to CDOIDAndVersion[]
+   */
+  @Override
+  protected void detachObjects(CDOID[] detachedObjects, CDOBranch branch, long timeStamp, OMMonitor monitor)
+  {
+    IMappingStrategy mappingStrategy = getStore().getMappingStrategy();
+    monitor.begin(detachedObjects.length);
+
+    try
+    {
+      InternalCDORevisionManager revisionManager = getStore().getRepository().getRevisionManager();
+      for (CDOID id : detachedObjects)
+      {
+        // TODO when CDOIDAndVersion is available:
+        // CDOID id = idAndVersion.getID(); //
+        // int version = idAndVersion.getVersion(); //
+
+        // but for now:
+
+        InternalCDORevision revision = revisionManager.getRevision(id, branch.getHead(), CDORevision.UNCHUNKED,
+            CDORevision.DEPTH_NONE, true);
+        int version = ObjectUtil.equals(branch, revision.getBranch()) ? revision.getVersion()
+            : CDOBranchVersion.FIRST_VERSION;
+
+        if (TRACER.isEnabled())
+        {
+          TRACER.format("Detaching object: {0}", id); //$NON-NLS-1$
+        }
+
+        EClass eClass = getObjectType(id);
+        IClassMapping mapping = mappingStrategy.getClassMapping(eClass);
+        mapping.detachObject(this, id, version, branch, timeStamp, monitor.fork());
+      }
+    }
+    finally
+    {
+      monitor.done();
+    }
+  }
+
+  public Connection getConnection()
+  {
+    return connection;
+  }
+
+  @Override
+  protected CDOID getNextCDOID(CDORevision revision)
+  {
+    return getStore().getIDHandler().getNextCDOID(revision);
+  }
+
+  @Override
+  protected void writeBlob(byte[] id, long size, InputStream inputStream) throws IOException
+  {
+    PreparedStatement stmt = null;
+
+    try
+    {
+      stmt = statementCache.getPreparedStatement(CDODBSchema.SQL_WRITE_BLOB, ReuseProbability.MEDIUM);
+      stmt.setString(1, HexUtil.bytesToHex(id));
+      stmt.setLong(2, size);
+      stmt.setBinaryStream(3, inputStream, (int)size);
+
+      DBUtil.update(stmt, true);
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  @Override
+  protected void writeClob(byte[] id, long size, Reader reader) throws IOException
+  {
+    PreparedStatement stmt = null;
+
+    try
+    {
+      stmt = statementCache.getPreparedStatement(CDODBSchema.SQL_WRITE_CLOB, ReuseProbability.MEDIUM);
+      stmt.setString(1, HexUtil.bytesToHex(id));
+      stmt.setLong(2, size);
+      stmt.setCharacterStream(3, reader, (int)size);
+
+      DBUtil.update(stmt, true);
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  @Override
+  protected final void doCommit(OMMonitor monitor)
+  {
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("--- DB COMMIT ---"); //$NON-NLS-1$
+    }
+
+    Async async = null;
+    monitor.begin();
+
+    try
+    {
+      try
+      {
+        async = monitor.forkAsync();
+        getConnection().commit();
+
+        if (maxID != CDOID.NULL)
+        {
+          // See bug 325097
+          getStore().getIDHandler().adjustLastObjectID(maxID);
+          maxID = CDOID.NULL;
+        }
+      }
+      finally
+      {
+        if (async != null)
+        {
+          async.stop();
+        }
+      }
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex);
+    }
+    finally
+    {
+      monitor.done();
+    }
+  }
+
+  @Override
+  protected final void doRollback(IStoreAccessor.CommitContext commitContext)
+  {
+    getStore().getMetaDataManager().clearMetaIDMappings();
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("--- DB ROLLBACK ---"); //$NON-NLS-1$
+    }
+
+    try
+    {
+      getConnection().rollback();
+
+      // Bugzilla 298632: Must rollback DBSchema to its prior state and drop the tables
+      getStore().getMappingStrategy().removeMapping(getConnection(), commitContext.getNewPackageUnits());
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex);
+    }
+  }
+
+  @Override
+  protected void doActivate() throws Exception
+  {
+    DBStore store = getStore();
+    connection = store.getConnection();
+    connectionKeepAliveTask = new ConnectionKeepAliveTask();
+
+    long keepAlivePeriod = ConnectionKeepAliveTask.EXECUTION_PERIOD;
+    Map<String, String> storeProps = store.getProperties();
+    if (storeProps != null)
+    {
+      String value = storeProps.get(IDBStore.Props.CONNECTION_KEEPALIVE_PERIOD);
+      if (value != null)
+      {
+        keepAlivePeriod = Long.parseLong(value) * 60L * 1000L;
+      }
+    }
+
+    store.getConnectionKeepAliveTimer().schedule(connectionKeepAliveTask, keepAlivePeriod, keepAlivePeriod);
+
+    // TODO - make this configurable?
+    statementCache = CDODBUtil.createStatementCache();
+    statementCache.setConnection(connection);
+    LifecycleUtil.activate(statementCache);
+  }
+
+  @Override
+  protected void doDeactivate() throws Exception
+  {
+    LifecycleUtil.deactivate(statementCache);
+    connectionKeepAliveTask.cancel();
+    DBUtil.close(connection);
+    connection = null;
+  }
+
+  @Override
+  protected void doPassivate() throws Exception
+  {
+    // this is called when the accessor is put back into the pool
+    // we want to make sure that no DB lock is held (see Bug 276926)
+    connection.rollback();
+  }
+
+  @Override
+  protected void doUnpassivate() throws Exception
+  {
+    // do nothing
+  }
+
+  public EPackage[] loadPackageUnit(InternalCDOPackageUnit packageUnit)
+  {
+    return getStore().getMetaDataManager().loadPackageUnit(getConnection(), packageUnit);
+  }
+
+  public Collection<InternalCDOPackageUnit> readPackageUnits()
+  {
+    return getStore().getMetaDataManager().readPackageUnits(getConnection());
+  }
+
+  public void writePackageUnits(InternalCDOPackageUnit[] packageUnits, OMMonitor monitor)
+  {
+    monitor.begin(2);
+
+    try
+    {
+      DBStore store = getStore();
+      Connection connection = getConnection();
+
+      IMetaDataManager metaDataManager = store.getMetaDataManager();
+      metaDataManager.writePackageUnits(connection, packageUnits, monitor.fork());
+
+      IMappingStrategy mappingStrategy = store.getMappingStrategy();
+      mappingStrategy.createMapping(connection, packageUnits, monitor.fork());
+    }
+    finally
+    {
+      monitor.done();
+    }
+  }
+
+  public Pair<Integer, Long> createBranch(int branchID, BranchInfo branchInfo)
+  {
+    checkBranchingSupport();
+    if (branchID == NEW_BRANCH)
+    {
+      branchID = getStore().getNextBranchID();
+    }
+    else if (branchID == NEW_LOCAL_BRANCH)
+    {
+      branchID = getStore().getNextLocalBranchID();
+    }
+
+    PreparedStatement stmt = null;
+
+    try
+    {
+      stmt = statementCache.getPreparedStatement(CDODBSchema.SQL_CREATE_BRANCH, ReuseProbability.LOW);
+      stmt.setInt(1, branchID);
+      stmt.setString(2, branchInfo.getName());
+      stmt.setInt(3, branchInfo.getBaseBranchID());
+      stmt.setLong(4, branchInfo.getBaseTimeStamp());
+
+      DBUtil.update(stmt, true);
+      getConnection().commit();
+      return new Pair<Integer, Long>(branchID, branchInfo.getBaseTimeStamp());
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  public BranchInfo loadBranch(int branchID)
+  {
+    checkBranchingSupport();
+    PreparedStatement stmt = null;
+    ResultSet resultSet = null;
+
+    try
+    {
+      stmt = statementCache.getPreparedStatement(CDODBSchema.SQL_LOAD_BRANCH, ReuseProbability.HIGH);
+      stmt.setInt(1, branchID);
+
+      resultSet = stmt.executeQuery();
+      if (!resultSet.next())
+      {
+        throw new DBException("Branch with ID " + branchID + " does not exist");
+      }
+
+      String name = resultSet.getString(1);
+      int baseBranchID = resultSet.getInt(2);
+      long baseTimeStamp = resultSet.getLong(3);
+      return new BranchInfo(name, baseBranchID, baseTimeStamp);
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex);
+    }
+    finally
+    {
+      DBUtil.close(resultSet);
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  public SubBranchInfo[] loadSubBranches(int baseID)
+  {
+    checkBranchingSupport();
+    PreparedStatement stmt = null;
+    ResultSet resultSet = null;
+
+    try
+    {
+      stmt = statementCache.getPreparedStatement(CDODBSchema.SQL_LOAD_SUB_BRANCHES, ReuseProbability.HIGH);
+      stmt.setInt(1, baseID);
+
+      resultSet = stmt.executeQuery();
+      List<SubBranchInfo> result = new ArrayList<SubBranchInfo>();
+      while (resultSet.next())
+      {
+        int id = resultSet.getInt(1);
+        String name = resultSet.getString(2);
+        long baseTimeStamp = resultSet.getLong(3);
+        result.add(new SubBranchInfo(id, name, baseTimeStamp));
+      }
+
+      return result.toArray(new SubBranchInfo[result.size()]);
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex);
+    }
+    finally
+    {
+      DBUtil.close(resultSet);
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  private void checkBranchingSupport()
+  {
+    if (!getStore().getMappingStrategy().hasBranchingSupport())
+    {
+      throw new UnsupportedOperationException("Mapping strategy does not support branching"); //$NON-NLS-1$
+    }
+  }
+
+  public int loadBranches(int startID, int endID, CDOBranchHandler handler)
+  {
+    int count = 0;
+    PreparedStatement stmt = null;
+    ResultSet resultSet = null;
+
+    InternalRepository repository = getSession().getManager().getRepository();
+    InternalCDOBranchManager branchManager = repository.getBranchManager();
+
+    try
+    {
+      stmt = statementCache.getPreparedStatement(CDODBSchema.SQL_LOAD_BRANCHES, ReuseProbability.HIGH);
+      stmt.setInt(1, startID);
+      stmt.setInt(2, endID > 0 ? endID : Integer.MAX_VALUE);
+
+      resultSet = stmt.executeQuery();
+      while (resultSet.next())
+      {
+        int branchID = resultSet.getInt(1);
+        String name = resultSet.getString(2);
+        int baseBranchID = resultSet.getInt(3);
+        long baseTimeStamp = resultSet.getLong(4);
+
+        InternalCDOBranch branch = branchManager.getBranch(branchID, new BranchInfo(name, baseBranchID, baseTimeStamp));
+        handler.handleBranch(branch);
+        ++count;
+      }
+
+      return count;
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex);
+    }
+    finally
+    {
+      DBUtil.close(resultSet);
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  public void loadCommitInfos(CDOBranch branch, long startTime, long endTime, CDOCommitInfoHandler handler)
+  {
+    StringBuilder builder = new StringBuilder();
+    builder.append("SELECT "); //$NON-NLS-1$
+    builder.append(CDODBSchema.COMMIT_INFOS_TIMESTAMP);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.COMMIT_INFOS_PREVIOUS_TIMESTAMP);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.COMMIT_INFOS_USER);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.COMMIT_INFOS_COMMENT);
+    if (branch == null)
+    {
+      builder.append(", "); //$NON-NLS-1$
+      builder.append(CDODBSchema.COMMIT_INFOS_BRANCH);
+    }
+
+    builder.append(" FROM "); //$NON-NLS-1$
+    builder.append(CDODBSchema.COMMIT_INFOS);
+    boolean where = false;
+
+    if (branch != null)
+    {
+      builder.append(where ? " AND " : " WHERE "); //$NON-NLS-1$ //$NON-NLS-2$
+      builder.append(CDODBSchema.COMMIT_INFOS_BRANCH);
+      builder.append("="); //$NON-NLS-1$
+      builder.append(branch.getID());
+      where = true;
+    }
+
+    if (startTime != CDOBranchPoint.UNSPECIFIED_DATE)
+    {
+      builder.append(where ? " AND " : " WHERE "); //$NON-NLS-1$ //$NON-NLS-2$
+      builder.append(CDODBSchema.COMMIT_INFOS_TIMESTAMP);
+      builder.append(">="); //$NON-NLS-1$
+      builder.append(startTime);
+      where = true;
+    }
+
+    if (endTime != CDOBranchPoint.UNSPECIFIED_DATE)
+    {
+      builder.append(where ? " AND " : " WHERE "); //$NON-NLS-1$ //$NON-NLS-2$
+      builder.append(CDODBSchema.COMMIT_INFOS_TIMESTAMP);
+      builder.append("<="); //$NON-NLS-1$
+      builder.append(endTime);
+      where = true;
+    }
+
+    builder.append(" ORDER BY "); //$NON-NLS-1$
+    builder.append(CDODBSchema.COMMIT_INFOS_TIMESTAMP);
+    String sql = builder.toString();
+
+    PreparedStatement stmt = null;
+    ResultSet resultSet = null;
+
+    InternalRepository repository = getStore().getRepository();
+    InternalCDOBranchManager branchManager = repository.getBranchManager();
+    InternalCDOCommitInfoManager commitInfoManager = repository.getCommitInfoManager();
+
+    try
+    {
+      stmt = statementCache.getPreparedStatement(sql, ReuseProbability.MEDIUM);
+
+      resultSet = stmt.executeQuery();
+      while (resultSet.next())
+      {
+        long timeStamp = resultSet.getLong(1);
+        long previousTimeStamp = resultSet.getLong(2);
+        String userID = resultSet.getString(3);
+        String comment = resultSet.getString(4);
+        CDOBranch infoBranch = branch;
+        if (infoBranch == null)
+        {
+          int id = resultSet.getInt(5);
+          infoBranch = branchManager.getBranch(id);
+        }
+
+        CDOCommitInfo commitInfo = commitInfoManager.createCommitInfo(infoBranch, timeStamp, previousTimeStamp, userID,
+            comment, null);
+        handler.handleCommitInfo(commitInfo);
+      }
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex);
+    }
+    finally
+    {
+      DBUtil.close(resultSet);
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  public Set<CDOID> readChangeSet(OMMonitor monitor, CDOChangeSetSegment... segments)
+  {
+    IMappingStrategy mappingStrategy = getStore().getMappingStrategy();
+    return mappingStrategy.readChangeSet(this, monitor, segments);
+  }
+
+  public void handleRevisions(EClass eClass, CDOBranch branch, long timeStamp, boolean exactTime,
+      CDORevisionHandler handler)
+  {
+    IMappingStrategy mappingStrategy = getStore().getMappingStrategy();
+    mappingStrategy.handleRevisions(this, eClass, branch, timeStamp, exactTime, new DBRevisionHandler(handler));
+  }
+
+  public void rawExport(CDODataOutput out, int fromBranchID, int toBranchID, long fromCommitTime, long toCommitTime)
+      throws IOException
+  {
+    DBStore store = getStore();
+    if (store.getRepository().getIDGenerationLocation() == IDGenerationLocation.STORE)
+    {
+      out.writeCDOID(store.getIDHandler().getLastObjectID()); // See bug 325097
+    }
+
+    String where = " WHERE " + CDODBSchema.BRANCHES_ID + " BETWEEN " + fromBranchID + " AND " + toBranchID;
+    DBUtil.serializeTable(out, connection, CDODBSchema.BRANCHES, null, where);
+
+    where = " WHERE " + CDODBSchema.COMMIT_INFOS_TIMESTAMP + " BETWEEN " + fromCommitTime + " AND " + toCommitTime;
+    DBUtil.serializeTable(out, connection, CDODBSchema.COMMIT_INFOS, null, where);
+
+    IIDHandler idHandler = store.getIDHandler();
+    idHandler.rawExport(connection, out, fromCommitTime, toCommitTime);
+
+    IMetaDataManager metaDataManager = store.getMetaDataManager();
+    metaDataManager.rawExport(connection, out, fromCommitTime, toCommitTime);
+
+    IMappingStrategy mappingStrategy = store.getMappingStrategy();
+    mappingStrategy.rawExport(this, out, fromBranchID, toBranchID, fromCommitTime, toCommitTime);
+  }
+
+  public void rawImport(CDODataInput in, int fromBranchID, int toBranchID, long fromCommitTime, long toCommitTime,
+      OMMonitor monitor) throws IOException
+  {
+    DBStore store = getStore();
+    if (store.getRepository().getIDGenerationLocation() == IDGenerationLocation.STORE)
+    {
+      store.getIDHandler().setLastObjectID(in.readCDOID()); // See bug 325097
+    }
+
+    IMappingStrategy mappingStrategy = store.getMappingStrategy();
+    int size = mappingStrategy.getClassMappings().size();
+    int commitWork = 4;
+    monitor.begin(commitWork + size + commitWork);
+
+    Collection<InternalCDOPackageUnit> packageUnits = new HashSet<InternalCDOPackageUnit>();
+
+    try
+    {
+      DBUtil.deserializeTable(in, connection, CDODBSchema.BRANCHES, monitor.fork());
+      DBUtil.deserializeTable(in, connection, CDODBSchema.COMMIT_INFOS, monitor.fork());
+      store.getIDHandler().rawImport(connection, in, fromCommitTime, toCommitTime, monitor.fork());
+      rawImportPackageUnits(in, fromCommitTime, toCommitTime, packageUnits, monitor.fork());
+      mappingStrategy.rawImport(this, in, fromCommitTime, toCommitTime, monitor.fork(size));
+      rawCommit(commitWork, monitor);
+    }
+    catch (RuntimeException ex)
+    {
+      rawRollback(packageUnits);
+      throw ex;
+    }
+    catch (IOException ex)
+    {
+      rawRollback(packageUnits);
+      throw ex;
+    }
+    finally
+    {
+      monitor.done();
+    }
+  }
+
+  private void rawRollback(Collection<InternalCDOPackageUnit> packageUnits)
+  {
+    try
+    {
+      connection.rollback();
+    }
+    catch (SQLException ex)
+    {
+      OM.LOG.error(ex);
+    }
+
+    getStore().getMappingStrategy().removeMapping(getConnection(),
+        packageUnits.toArray(new InternalCDOPackageUnit[packageUnits.size()]));
+  }
+
+  protected void rawImportPackageUnits(CDODataInput in, long fromCommitTime, long toCommitTime,
+      Collection<InternalCDOPackageUnit> packageUnits, OMMonitor monitor) throws IOException
+  {
+    monitor.begin(2);
+
+    try
+    {
+      DBStore store = getStore();
+      IMetaDataManager metaDataManager = store.getMetaDataManager();
+
+      packageUnits.addAll(metaDataManager.rawImport(connection, in, fromCommitTime, toCommitTime, monitor.fork()));
+
+      InternalRepository repository = store.getRepository();
+      InternalCDOPackageRegistry packageRegistry = repository.getPackageRegistry(false);
+
+      for (InternalCDOPackageUnit packageUnit : packageUnits)
+      {
+        packageRegistry.putPackageUnit(packageUnit);
+      }
+
+      IMappingStrategy mappingStrategy = store.getMappingStrategy();
+
+      // Using another connection because CREATE TABLE (which is called in createMapping) on H2 databases does a commit.
+      Connection connection2 = null;
+      try
+      {
+        connection2 = store.getConnection();
+
+        mappingStrategy.createMapping(connection2,
+            packageUnits.toArray(new InternalCDOPackageUnit[packageUnits.size()]), monitor.fork());
+      }
+      finally
+      {
+        DBUtil.close(connection2);
+      }
+    }
+    finally
+    {
+      monitor.done();
+    }
+  }
+
+  public void rawStore(InternalCDOPackageUnit[] packageUnits, OMMonitor monitor)
+  {
+    writePackageUnits(packageUnits, monitor);
+  }
+
+  public void rawStore(InternalCDORevision revision, OMMonitor monitor)
+  {
+    CDOID id = revision.getID();
+
+    CDOClassifierRef classifierRef = getStore().getMappingStrategy().readObjectType(this, id);
+    boolean isFirstRevision = classifierRef == null;
+
+    if (!isFirstRevision)
+    {
+      EClass eClass = revision.getEClass();
+      boolean namesMatch = classifierRef.getClassifierName().equals(eClass.getName());
+      boolean packagesMatch = classifierRef.getPackageURI().equals(eClass.getEPackage().getNsURI());
+      if (!namesMatch || !packagesMatch)
+      {
+        throw new IllegalStateException();
+      }
+    }
+
+    writeRevision(revision, isFirstRevision, false, monitor);
+    getStore().getIDHandler().adjustLastObjectID(id);
+  }
+
+  public void rawStore(byte[] id, long size, InputStream inputStream) throws IOException
+  {
+    writeBlob(id, size, inputStream);
+  }
+
+  public void rawStore(byte[] id, long size, Reader reader) throws IOException
+  {
+    writeClob(id, size, reader);
+  }
+
+  public void rawStore(CDOBranch branch, long timeStamp, long previousTimeStamp, String userID, String comment,
+      OMMonitor monitor)
+  {
+    writeCommitInfo(branch, timeStamp, previousTimeStamp, userID, comment, monitor);
+  }
+
+  @Deprecated
+  public void rawDelete(CDOID id, int version, CDOBranch branch, EClass eClass, OMMonitor monitor)
+  {
+    throw new UnsupportedOperationException();
+
+    // IMappingStrategy mappingStrategy = getStore().getMappingStrategy();
+    // if (eClass == null)
+    // {
+    // eClass = getObjectType(id);
+    // }
+    //
+    // IClassMapping mapping = mappingStrategy.getClassMapping(eClass);
+    // mapping.detachObject(this, id, version, branch, CDOBranchPoint.UNSPECIFIED_DATE, monitor);
+  }
+
+  public void rawCommit(double commitWork, OMMonitor monitor)
+  {
+    monitor.begin();
+    Async async = monitor.forkAsync();
+
+    try
+    {
+      connection.commit();
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex);
+    }
+    finally
+    {
+      async.stop();
+      monitor.done();
+    }
+  }
+
+  public LockArea createLockArea(String userID, CDOBranchPoint branchPoint, boolean readOnly,
+      Map<CDOID, LockGrade> locks)
+  {
+    return createLockArea(null, userID, branchPoint, readOnly, locks);
+  }
+
+  public LockArea createLockArea(String durableLockingID, String userID, CDOBranchPoint branchPoint, boolean readOnly,
+      Map<CDOID, LockGrade> locks)
+  {
+    DurableLockingManager manager = getStore().getDurableLockingManager();
+    return manager.createLockArea(this, durableLockingID, userID, branchPoint, readOnly, locks);
+  }
+
+  public void updateLockArea(LockArea area)
+  {
+    DurableLockingManager manager = getStore().getDurableLockingManager();
+    manager.updateLockArea(this, area);
+  }
+
+  public LockArea getLockArea(String durableLockingID) throws LockAreaNotFoundException
+  {
+    DurableLockingManager manager = getStore().getDurableLockingManager();
+    return manager.getLockArea(this, durableLockingID);
+  }
+
+  public void getLockAreas(String userIDPrefix, Handler handler)
+  {
+    DurableLockingManager manager = getStore().getDurableLockingManager();
+    manager.getLockAreas(this, userIDPrefix, handler);
+  }
+
+  public void deleteLockArea(String durableLockingID)
+  {
+    DurableLockingManager manager = getStore().getDurableLockingManager();
+    manager.deleteLockArea(this, durableLockingID);
+  }
+
+  public void lock(String durableLockingID, LockType type, Collection<? extends Object> objectsToLock)
+  {
+    DurableLockingManager manager = getStore().getDurableLockingManager();
+    manager.lock(this, durableLockingID, type, objectsToLock);
+  }
+
+  public void unlock(String durableLockingID, LockType type, Collection<? extends Object> objectsToUnlock)
+  {
+    DurableLockingManager manager = getStore().getDurableLockingManager();
+    manager.unlock(this, durableLockingID, type, objectsToUnlock);
+  }
+
+  public void unlock(String durableLockingID)
+  {
+    DurableLockingManager manager = getStore().getDurableLockingManager();
+    manager.unlock(this, durableLockingID);
+  }
+
+  /**
+   * @author Stefan Winkler
+   */
+  private class ConnectionKeepAliveTask extends TimerTask
+  {
+    public static final long EXECUTION_PERIOD = 1000 * 60 * 60 * 4; // 4 hours
+
+    @Override
+    public void run()
+    {
+      Statement stmt = null;
+
+      try
+      {
+        if (TRACER.isEnabled())
+        {
+          TRACER.trace("DB connection keep-alive task activated"); //$NON-NLS-1$
+        }
+
+        stmt = connection.createStatement();
+        stmt.executeQuery("SELECT 1 FROM " + CDODBSchema.PROPERTIES); //$NON-NLS-1$
+      }
+      catch (java.sql.SQLException ex)
+      {
+        OM.LOG.error("DB connection keep-alive failed", ex); //$NON-NLS-1$
+
+        // Assume the connection has failed.
+        try
+        {
+          LifecycleUtil.deactivate(DBStoreAccessor.this);
+          LifecycleUtil.activate(DBStoreAccessor.this);
+        }
+        catch (Exception ex2)
+        {
+          OM.LOG.error("DB connection reconnect failed", ex2); //$NON-NLS-1$
+        }
+      }
+      catch (Exception ex) // Important: Do not throw any unchecked exceptions to the TimerThread!!!
+      {
+        OM.LOG.error("DB connection keep-alive failed", ex); //$NON-NLS-1$
+      }
+      finally
+      {
+        DBUtil.close(stmt);
+      }
+    }
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStoreChunkReader.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStoreChunkReader.java
new file mode 100644
index 0000000..59287fa
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStoreChunkReader.java
@@ -0,0 +1,94 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - Bug 283998: [DB] Chunk reading for multiple chunks fails
+ *    Victor Roldan Betancort - Bug 283998: [DB] Chunk reading for multiple chunks fails
+ */
+package org.eclipse.emf.cdo.server.internal.db;
+
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.server.db.IDBStoreChunkReader;
+import org.eclipse.emf.cdo.server.db.mapping.IClassMapping;
+import org.eclipse.emf.cdo.server.db.mapping.IListMapping;
+import org.eclipse.emf.cdo.server.db.mapping.IMappingStrategy;
+import org.eclipse.emf.cdo.spi.server.StoreChunkReader;
+
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+import java.util.List;
+
+/**
+ * @author Eike Stepper
+ */
+public class DBStoreChunkReader extends StoreChunkReader implements IDBStoreChunkReader
+{
+  private IListMapping referenceMapping;
+
+  private StringBuilder builder = new StringBuilder();
+
+  public DBStoreChunkReader(DBStoreAccessor accessor, CDORevision revision, EStructuralFeature feature)
+  {
+    super(accessor, revision, feature);
+    IMappingStrategy mappingStrategy = accessor.getStore().getMappingStrategy();
+    IClassMapping mapping = mappingStrategy.getClassMapping(revision.getEClass());
+    referenceMapping = mapping.getListMapping(feature);
+  }
+
+  @Override
+  public DBStoreAccessor getAccessor()
+  {
+    return (DBStoreAccessor)super.getAccessor();
+  }
+
+  @Override
+  public void addSimpleChunk(int index)
+  {
+    super.addSimpleChunk(index);
+    prepareAddition();
+
+    builder.append(CDODBSchema.LIST_IDX);
+    builder.append('=');
+    builder.append(index);
+  }
+
+  @Override
+  public void addRangedChunk(int fromIndex, int toIndex)
+  {
+    super.addRangedChunk(fromIndex, toIndex);
+    prepareAddition();
+
+    builder.append(CDODBSchema.LIST_IDX);
+    builder.append(" BETWEEN "); //$NON-NLS-1$
+    builder.append(fromIndex);
+    builder.append(" AND "); //$NON-NLS-1$
+    builder.append(toIndex - 1);
+  }
+
+  public List<Chunk> executeRead()
+  {
+    List<Chunk> chunks = getChunks();
+    if (chunks.size() > 1)
+    {
+      builder.insert(0, '(');
+      builder.append(')');
+    }
+
+    referenceMapping.readChunks(this, chunks, builder.toString());
+    return chunks;
+  }
+
+  private void prepareAddition()
+  {
+    // If not empty, a chunk has been already added, and the next condition needs to be OR-ed
+    if (builder.length() > 0)
+    {
+      builder.append(" OR "); //$NON-NLS-1$
+    }
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStoreFactory.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStoreFactory.java
new file mode 100644
index 0000000..2290289
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStoreFactory.java
@@ -0,0 +1,130 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - 271444: [DB] Multiple refactorings bug 271444
+ *    Caspar De Groot - maintenance  
+ */
+package org.eclipse.emf.cdo.server.internal.db;
+
+import org.eclipse.emf.cdo.server.IStore;
+import org.eclipse.emf.cdo.server.IStoreFactory;
+import org.eclipse.emf.cdo.server.db.CDODBUtil;
+import org.eclipse.emf.cdo.server.db.mapping.IMappingStrategy;
+import org.eclipse.emf.cdo.spi.server.RepositoryConfigurator;
+
+import org.eclipse.net4j.db.DBUtil;
+import org.eclipse.net4j.db.IDBAdapter;
+import org.eclipse.net4j.db.IDBConnectionProvider;
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.NodeList;
+
+import javax.sql.DataSource;
+
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * @author Eike Stepper
+ */
+public class DBStoreFactory implements IStoreFactory
+{
+  public DBStoreFactory()
+  {
+  }
+
+  public String getStoreType()
+  {
+    return DBStore.TYPE;
+  }
+
+  public IStore createStore(String repositoryName, Map<String, String> repositoryProperties, Element storeConfig)
+  {
+    IMappingStrategy mappingStrategy = getMappingStrategy(repositoryName, repositoryProperties, storeConfig);
+    IDBAdapter dbAdapter = getDBAdapter(storeConfig);
+    DataSource dataSource = getDataSource(storeConfig);
+    IDBConnectionProvider connectionProvider = DBUtil.createConnectionProvider(dataSource);
+
+    DBStore store = new DBStore();
+    store.setMappingStrategy(mappingStrategy);
+    store.setDBAdapter(dbAdapter);
+    store.setDbConnectionProvider(connectionProvider);
+
+    Map<String, String> storeProperties = RepositoryConfigurator.getProperties(storeConfig, 1);
+    store.setProperties(storeProperties);
+
+    return store;
+  }
+
+  private IMappingStrategy getMappingStrategy(String repositoryName, Map<String, String> repositoryProperties,
+      Element storeConfig)
+  {
+    NodeList mappingStrategyConfigs = storeConfig.getElementsByTagName("mappingStrategy"); //$NON-NLS-1$
+    if (mappingStrategyConfigs.getLength() != 1)
+    {
+      throw new IllegalStateException("Exactly one mapping strategy must be configured for DB store"); //$NON-NLS-1$
+    }
+
+    Element mappingStrategyConfig = (Element)mappingStrategyConfigs.item(0);
+    String mappingStrategyType = mappingStrategyConfig.getAttribute("type"); //$NON-NLS-1$
+    IMappingStrategy mappingStrategy = CDODBUtil.createMappingStrategy(mappingStrategyType);
+    if (mappingStrategy == null)
+    {
+      throw new IllegalArgumentException("Unknown mapping strategy: " + mappingStrategyType); //$NON-NLS-1$
+    }
+
+    Map<String, String> properties = RepositoryConfigurator.getProperties(mappingStrategyConfig, 1);
+    properties.put("repositoryName", repositoryName);
+    properties.putAll(repositoryProperties);
+    mappingStrategy.setProperties(properties);
+
+    return mappingStrategy;
+  }
+
+  private IDBAdapter getDBAdapter(Element storeConfig)
+  {
+    NodeList dbAdapterConfigs = storeConfig.getElementsByTagName("dbAdapter"); //$NON-NLS-1$
+    if (dbAdapterConfigs.getLength() != 1)
+    {
+      throw new IllegalStateException("Exactly one dbAdapter must be configured for DB store"); //$NON-NLS-1$
+    }
+
+    Element dbAdapterConfig = (Element)dbAdapterConfigs.item(0);
+    String dbAdapterName = dbAdapterConfig.getAttribute("name"); //$NON-NLS-1$
+    IDBAdapter dbAdapter = DBUtil.getDBAdapter(dbAdapterName);
+    if (dbAdapter == null)
+    {
+      throw new IllegalArgumentException("Unknown DB adapter: " + dbAdapterName); //$NON-NLS-1$
+    }
+
+    return dbAdapter;
+  }
+
+  private DataSource getDataSource(Element storeConfig)
+  {
+    NodeList dataSourceConfigs = storeConfig.getElementsByTagName("dataSource"); //$NON-NLS-1$
+    if (dataSourceConfigs.getLength() != 1)
+    {
+      throw new IllegalStateException("Exactly one dataSource must be configured for DB store"); //$NON-NLS-1$
+    }
+
+    Properties properties = new Properties();
+    Element dataSourceConfig = (Element)dataSourceConfigs.item(0);
+    NamedNodeMap attributes = dataSourceConfig.getAttributes();
+    for (int i = 0; i < attributes.getLength(); i++)
+    {
+      Attr attribute = (Attr)attributes.item(i);
+      properties.put(attribute.getName(), attribute.getValue());
+    }
+
+    return DBUtil.createDataSource(properties);
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DurableLockingManager.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DurableLockingManager.java
new file mode 100644
index 0000000..7fbd726
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DurableLockingManager.java
@@ -0,0 +1,687 @@
+/**

+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ * 

+ * Contributors:

+ *    Eike Stepper - initial API and implementation

+ */

+package org.eclipse.emf.cdo.server.internal.db;

+

+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;

+import org.eclipse.emf.cdo.common.id.CDOID;

+import org.eclipse.emf.cdo.common.lock.CDOLockUtil;

+import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockArea;

+import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockArea.Handler;

+import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockAreaAlreadyExistsException;

+import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockAreaNotFoundException;

+import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockGrade;

+import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;

+import org.eclipse.emf.cdo.server.db.IIDHandler;

+import org.eclipse.emf.cdo.server.db.IPreparedStatementCache;

+import org.eclipse.emf.cdo.server.db.IPreparedStatementCache.ReuseProbability;

+import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranchManager;

+import org.eclipse.emf.cdo.spi.server.InternalLockManager;

+

+import org.eclipse.net4j.db.DBException;

+import org.eclipse.net4j.db.DBType;

+import org.eclipse.net4j.db.DBUtil;

+import org.eclipse.net4j.db.ddl.IDBField;

+import org.eclipse.net4j.db.ddl.IDBIndex;

+import org.eclipse.net4j.db.ddl.IDBSchema;

+import org.eclipse.net4j.db.ddl.IDBTable;

+import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;

+import org.eclipse.net4j.util.lifecycle.Lifecycle;

+

+import java.sql.Connection;

+import java.sql.PreparedStatement;

+import java.sql.ResultSet;

+import java.sql.SQLException;

+import java.sql.Statement;

+import java.util.Collection;

+import java.util.HashMap;

+import java.util.Map;

+import java.util.Map.Entry;

+

+/**

+ * @author Eike Stepper

+ */

+public class DurableLockingManager extends Lifecycle

+{

+  private DBStore store;

+

+  private InternalCDOBranchManager branchManager;

+

+  private IIDHandler idHandler;

+

+  private IDBTable lockAreas;

+

+  private IDBField lockAreasID;

+

+  private IDBField lockAreasUser;

+

+  private IDBField lockAreasBranch;

+

+  private IDBField lockAreasTime;

+

+  private IDBField lockAreasReadOnly;

+

+  private IDBTable locks;

+

+  private IDBField locksArea;

+

+  private IDBField locksObject;

+

+  private IDBField locksGrade;

+

+  private String sqlInsertLockArea;

+

+  private String sqlSelectLockArea;

+

+  private String sqlSelectAllLockAreas;

+

+  private String sqlSelectLockAreas;

+

+  private String sqlDeleteLockArea;

+

+  private String sqlSelectLocks;

+

+  private String sqlSelectLock;

+

+  private String sqlInsertLock;

+

+  private String sqlUpdateLock;

+

+  private String sqlDeleteLock;

+

+  private String sqlDeleteLocks;

+

+  public DurableLockingManager(DBStore store)

+  {

+    this.store = store;

+  }

+

+  public synchronized LockArea createLockArea(DBStoreAccessor accessor, String durableLockingID, String userID,

+      CDOBranchPoint branchPoint, boolean readOnly, Map<CDOID, LockGrade> locks)

+  {

+    try

+    {

+      if (durableLockingID == null)

+      {

+        durableLockingID = getNextDurableLockingID(accessor);

+      }

+      else

+      {

+        // If the caller is specifying the ID, make sure there is no area with this ID yet

+        //

+        try

+        {

+          getLockArea(accessor, durableLockingID);

+          throw new LockAreaAlreadyExistsException(durableLockingID);

+        }

+        catch (LockAreaNotFoundException good)

+        {

+        }

+      }

+

+      IPreparedStatementCache statementCache = accessor.getStatementCache();

+      PreparedStatement stmt = null;

+

+      try

+      {

+        stmt = statementCache.getPreparedStatement(sqlInsertLockArea, ReuseProbability.LOW);

+        stmt.setString(1, durableLockingID);

+        stmt.setString(2, userID);

+        stmt.setInt(3, branchPoint.getBranch().getID());

+        stmt.setLong(4, branchPoint.getTimeStamp());

+        stmt.setBoolean(5, readOnly);

+

+        DBUtil.update(stmt, true);

+      }

+      catch (SQLException e)

+      {

+        throw new DBException(e);

+      }

+      finally

+      {

+        statementCache.releasePreparedStatement(stmt);

+      }

+

+      if (!locks.isEmpty())

+      {

+        insertLocks(accessor, durableLockingID, locks);

+      }

+

+      accessor.getConnection().commit();

+

+      return CDOLockUtil.createLockArea(durableLockingID, userID, branchPoint, readOnly, locks);

+    }

+    catch (SQLException ex)

+    {

+      throw new DBException(ex);

+    }

+  }

+

+  private void insertLocks(DBStoreAccessor accessor, String durableLockingID, Map<CDOID, LockGrade> locks)

+  {

+    IPreparedStatementCache statementCache = accessor.getStatementCache();

+    PreparedStatement stmt = null;

+

+    try

+    {

+      stmt = statementCache.getPreparedStatement(sqlInsertLock, ReuseProbability.MEDIUM);

+      stmt.setString(1, durableLockingID);

+

+      for (Entry<CDOID, LockGrade> entry : locks.entrySet())

+      {

+        CDOID id = entry.getKey();

+        int grade = entry.getValue().getValue();

+

+        idHandler.setCDOID(stmt, 2, id);

+        stmt.setInt(3, grade);

+

+        DBUtil.update(stmt, true);

+      }

+    }

+    catch (SQLException e)

+    {

+      throw new DBException(e);

+    }

+    finally

+    {

+      statementCache.releasePreparedStatement(stmt);

+    }

+  }

+

+  public LockArea getLockArea(DBStoreAccessor accessor, String durableLockingID) throws LockAreaNotFoundException

+  {

+    IPreparedStatementCache statementCache = accessor.getStatementCache();

+    PreparedStatement stmt = null;

+    ResultSet resultSet = null;

+

+    try

+    {

+      stmt = statementCache.getPreparedStatement(sqlSelectLockArea, ReuseProbability.MEDIUM);

+      stmt.setString(1, durableLockingID);

+      resultSet = stmt.executeQuery();

+

+      if (!resultSet.next())

+      {

+        throw new LockAreaNotFoundException(durableLockingID);

+      }

+

+      String userID = resultSet.getString(1);

+      int branchID = resultSet.getInt(2);

+      long timeStamp = resultSet.getLong(3);

+      boolean readOnly = resultSet.getBoolean(4);

+

+      return makeLockArea(accessor, durableLockingID, userID, branchID, timeStamp, readOnly);

+    }

+    catch (SQLException e)

+    {

+      throw new DBException(e);

+    }

+    finally

+    {

+      DBUtil.close(resultSet);

+      statementCache.releasePreparedStatement(stmt);

+    }

+  }

+

+  public void getLockAreas(DBStoreAccessor accessor, String userIDPrefix, Handler handler)

+  {

+    IPreparedStatementCache statementCache = accessor.getStatementCache();

+    PreparedStatement stmt = null;

+    ResultSet resultSet = null;

+

+    try

+    {

+      if (userIDPrefix.length() == 0)

+      {

+        stmt = statementCache.getPreparedStatement(sqlSelectAllLockAreas, ReuseProbability.MEDIUM);

+      }

+      else

+      {

+        stmt = statementCache.getPreparedStatement(sqlSelectLockAreas, ReuseProbability.MEDIUM);

+        stmt.setString(1, userIDPrefix + "%");

+      }

+

+      resultSet = stmt.executeQuery();

+      while (resultSet.next())

+      {

+        String durableLockingID = resultSet.getString(1);

+        String userID = resultSet.getString(2);

+        int branchID = resultSet.getInt(3);

+        long timeStamp = resultSet.getLong(4);

+        boolean readOnly = resultSet.getBoolean(5);

+

+        LockArea area = makeLockArea(accessor, durableLockingID, userID, branchID, timeStamp, readOnly);

+        if (!handler.handleLockArea(area))

+        {

+          break;

+        }

+      }

+    }

+    catch (SQLException e)

+    {

+      throw new DBException(e);

+    }

+    finally

+    {

+      DBUtil.close(resultSet);

+      statementCache.releasePreparedStatement(stmt);

+    }

+  }

+

+  public void deleteLockArea(DBStoreAccessor accessor, String durableLockingID)

+  {

+    try

+    {

+      unlockWithoutCommit(accessor, durableLockingID);

+

+      IPreparedStatementCache statementCache = accessor.getStatementCache();

+      PreparedStatement stmt = null;

+

+      try

+      {

+        stmt = statementCache.getPreparedStatement(sqlDeleteLockArea, ReuseProbability.LOW);

+        stmt.setString(1, durableLockingID);

+

+        DBUtil.update(stmt, true);

+      }

+      catch (SQLException e)

+      {

+        throw new DBException(e);

+      }

+      finally

+      {

+        statementCache.releasePreparedStatement(stmt);

+      }

+

+      accessor.getConnection().commit();

+    }

+    catch (SQLException e)

+    {

+      throw new DBException(e);

+    }

+  }

+

+  public void updateLockArea(DBStoreAccessor accessor, LockArea area)

+  {

+    try

+    {

+      String areaID = area.getDurableLockingID();

+      unlockWithoutCommit(accessor, areaID);

+      insertLocks(accessor, areaID, area.getLocks());

+

+      accessor.getConnection().commit();

+    }

+    catch (SQLException e)

+    {

+      throw new DBException(e);

+    }

+  }

+

+  public void lock(DBStoreAccessor accessor, String durableLockingID, LockType type,

+      Collection<? extends Object> objectsToLock)

+  {

+    changeLocks(accessor, durableLockingID, type, objectsToLock, true);

+  }

+

+  public void unlock(DBStoreAccessor accessor, String durableLockingID, LockType type,

+      Collection<? extends Object> objectsToUnlock)

+  {

+    changeLocks(accessor, durableLockingID, type, objectsToUnlock, false);

+  }

+

+  public void unlock(DBStoreAccessor accessor, String durableLockingID)

+  {

+    try

+    {

+      unlockWithoutCommit(accessor, durableLockingID);

+      accessor.getConnection().commit();

+    }

+    catch (SQLException e)

+    {

+      throw new DBException(e);

+    }

+  }

+

+  private void unlockWithoutCommit(DBStoreAccessor accessor, String durableLockingID)

+  {

+    IPreparedStatementCache statementCache = accessor.getStatementCache();

+    PreparedStatement stmt = null;

+

+    try

+    {

+      stmt = statementCache.getPreparedStatement(sqlDeleteLocks, ReuseProbability.MEDIUM);

+      stmt.setString(1, durableLockingID);

+

+      DBUtil.update(stmt, false);

+    }

+    catch (SQLException e)

+    {

+      throw new DBException(e);

+    }

+    finally

+    {

+      statementCache.releasePreparedStatement(stmt);

+    }

+  }

+

+  @Override

+  protected void doActivate() throws Exception

+  {

+    super.doActivate();

+

+    branchManager = store.getRepository().getBranchManager();

+    idHandler = store.getIDHandler();

+

+    IDBSchema schema = store.getDBSchema();

+

+    // Lock areas

+    lockAreas = schema.addTable("cdo_lock_areas");

+    lockAreasID = lockAreas.addField("id", DBType.VARCHAR);

+    lockAreasUser = lockAreas.addField("user_id", DBType.VARCHAR);

+    lockAreasBranch = lockAreas.addField("view_branch", DBType.INTEGER);

+    lockAreasTime = lockAreas.addField("view_time", DBType.BIGINT);

+    lockAreasReadOnly = lockAreas.addField("read_only", DBType.BOOLEAN);

+

+    lockAreas.addIndex(IDBIndex.Type.PRIMARY_KEY, lockAreasID);

+    lockAreas.addIndex(IDBIndex.Type.NON_UNIQUE, lockAreasUser);

+

+    // Locks

+    locks = schema.addTable("cdo_locks");

+    locksArea = locks.addField("area_id", DBType.VARCHAR);

+    locksObject = locks.addField("object_id", idHandler.getDBType());

+    locksGrade = locks.addField("lock_grade", DBType.INTEGER);

+

+    locks.addIndex(IDBIndex.Type.PRIMARY_KEY, locksArea, locksObject);

+    locks.addIndex(IDBIndex.Type.NON_UNIQUE, locksArea);

+

+    IDBStoreAccessor writer = store.getWriter(null);

+    Connection connection = writer.getConnection();

+    Statement statement = null;

+

+    try

+    {

+      statement = connection.createStatement();

+      store.getDBAdapter().createTable(lockAreas, statement);

+      store.getDBAdapter().createTable(locks, statement);

+      connection.commit();

+    }

+    catch (SQLException ex)

+    {

+      connection.rollback();

+      throw new DBException(ex);

+    }

+    finally

+    {

+      DBUtil.close(statement);

+      writer.release();

+    }

+

+    StringBuilder builder = new StringBuilder();

+    builder.append("INSERT INTO "); //$NON-NLS-1$

+    builder.append(lockAreas);

+    builder.append("("); //$NON-NLS-1$

+    builder.append(lockAreasID);

+    builder.append(","); //$NON-NLS-1$

+    builder.append(lockAreasUser);

+    builder.append(","); //$NON-NLS-1$

+    builder.append(lockAreasBranch);

+    builder.append(","); //$NON-NLS-1$

+    builder.append(lockAreasTime);

+    builder.append(","); //$NON-NLS-1$

+    builder.append(lockAreasReadOnly);

+    builder.append(") VALUES (?, ?, ?, ?, ?)"); //$NON-NLS-1$

+    sqlInsertLockArea = builder.toString();

+

+    builder = new StringBuilder();

+    builder.append("SELECT "); //$NON-NLS-1$

+    builder.append(lockAreasUser);

+    builder.append(","); //$NON-NLS-1$

+    builder.append(lockAreasBranch);

+    builder.append(","); //$NON-NLS-1$

+    builder.append(lockAreasTime);

+    builder.append(","); //$NON-NLS-1$

+    builder.append(lockAreasReadOnly);

+    builder.append(" FROM "); //$NON-NLS-1$

+    builder.append(lockAreas);

+    builder.append(" WHERE "); //$NON-NLS-1$

+    builder.append(lockAreasID);

+    builder.append("=?"); //$NON-NLS-1$

+    sqlSelectLockArea = builder.toString();

+

+    builder = new StringBuilder();

+    builder.append("SELECT "); //$NON-NLS-1$

+    builder.append(lockAreasID);

+    builder.append(","); //$NON-NLS-1$

+    builder.append(lockAreasUser);

+    builder.append(","); //$NON-NLS-1$

+    builder.append(lockAreasBranch);

+    builder.append(","); //$NON-NLS-1$

+    builder.append(lockAreasTime);

+    builder.append(","); //$NON-NLS-1$

+    builder.append(lockAreasReadOnly);

+    builder.append(" FROM "); //$NON-NLS-1$

+    builder.append(lockAreas);

+    sqlSelectAllLockAreas = builder.toString();

+

+    builder.append(" WHERE "); //$NON-NLS-1$

+    builder.append(lockAreasUser);

+    builder.append(" LIKE ?"); //$NON-NLS-1$

+    sqlSelectLockAreas = builder.toString();

+

+    builder = new StringBuilder();

+    builder.append("DELETE FROM "); //$NON-NLS-1$

+    builder.append(lockAreas);

+    builder.append(" WHERE "); //$NON-NLS-1$

+    builder.append(lockAreasID);

+    builder.append("=?"); //$NON-NLS-1$

+    sqlDeleteLockArea = builder.toString();

+

+    builder = new StringBuilder();

+    builder.append("SELECT "); //$NON-NLS-1$

+    builder.append(locksObject);

+    builder.append(","); //$NON-NLS-1$

+    builder.append(locksGrade);

+    builder.append(" FROM "); //$NON-NLS-1$

+    builder.append(locks);

+    builder.append(" WHERE "); //$NON-NLS-1$

+    builder.append(locksArea);

+    builder.append("=?"); //$NON-NLS-1$

+    sqlSelectLocks = builder.toString();

+

+    builder = new StringBuilder();

+    builder.append("SELECT "); //$NON-NLS-1$

+    builder.append(locksGrade);

+    builder.append(" FROM "); //$NON-NLS-1$

+    builder.append(locks);

+    builder.append(" WHERE "); //$NON-NLS-1$

+    builder.append(locksArea);

+    builder.append("=? AND "); //$NON-NLS-1$

+    builder.append(locksObject);

+    builder.append("=?"); //$NON-NLS-1$

+    sqlSelectLock = builder.toString();

+

+    builder = new StringBuilder();

+    builder.append("INSERT INTO "); //$NON-NLS-1$

+    builder.append(locks);

+    builder.append("("); //$NON-NLS-1$

+    builder.append(locksArea);

+    builder.append(","); //$NON-NLS-1$

+    builder.append(locksObject);

+    builder.append(","); //$NON-NLS-1$

+    builder.append(locksGrade);

+    builder.append(") VALUES (?, ?, ?)"); //$NON-NLS-1$

+    sqlInsertLock = builder.toString();

+

+    builder = new StringBuilder();

+    builder.append("UPDATE "); //$NON-NLS-1$

+    builder.append(locks);

+    builder.append(" SET "); //$NON-NLS-1$

+    builder.append(locksGrade);

+    builder.append("=? "); //$NON-NLS-1$

+    builder.append(" WHERE "); //$NON-NLS-1$

+    builder.append(locksArea);

+    builder.append("=? AND "); //$NON-NLS-1$

+    builder.append(locksObject);

+    builder.append("=?"); //$NON-NLS-1$

+    sqlUpdateLock = builder.toString();

+

+    builder = new StringBuilder();

+    builder.append("DELETE FROM "); //$NON-NLS-1$

+    builder.append(locks);

+    builder.append(" WHERE "); //$NON-NLS-1$

+    builder.append(locksArea);

+    builder.append("=? AND "); //$NON-NLS-1$

+    builder.append(locksObject);

+    builder.append("=?"); //$NON-NLS-1$

+    sqlDeleteLock = builder.toString();

+

+    builder = new StringBuilder();

+    builder.append("DELETE FROM "); //$NON-NLS-1$

+    builder.append(locks);

+    builder.append(" WHERE "); //$NON-NLS-1$

+    builder.append(locksArea);

+    builder.append("=?"); //$NON-NLS-1$

+    sqlDeleteLocks = builder.toString();

+  }

+

+  private String getNextDurableLockingID(DBStoreAccessor accessor)

+  {

+    for (;;)

+    {

+      String durableLockingID = CDOLockUtil.createDurableLockingID();

+

+      try

+      {

+        getLockArea(accessor, durableLockingID); // Check uniqueness

+        // Not unique; try once more...

+      }

+      catch (LockAreaNotFoundException ex)

+      {

+        return durableLockingID;

+      }

+    }

+  }

+

+  private LockArea makeLockArea(DBStoreAccessor accessor, String durableLockingID, String userID, int branchID,

+      long timeStamp, boolean readOnly)

+  {

+    CDOBranchPoint branchPoint = branchManager.getBranch(branchID).getPoint(timeStamp);

+    Map<CDOID, LockGrade> lockMap = getLockMap(accessor, durableLockingID);

+    return CDOLockUtil.createLockArea(durableLockingID, userID, branchPoint, readOnly, lockMap);

+  }

+

+  private Map<CDOID, LockGrade> getLockMap(DBStoreAccessor accessor, String durableLockingID)

+  {

+    IPreparedStatementCache statementCache = accessor.getStatementCache();

+    PreparedStatement stmt = null;

+    ResultSet resultSet = null;

+

+    try

+    {

+      stmt = statementCache.getPreparedStatement(sqlSelectLocks, ReuseProbability.MEDIUM);

+      stmt.setString(1, durableLockingID);

+      resultSet = stmt.executeQuery();

+

+      Map<CDOID, LockGrade> lockMap = new HashMap<CDOID, LockGrade>();

+      while (resultSet.next())

+      {

+        CDOID id = idHandler.getCDOID(resultSet, 1);

+        int grade = resultSet.getInt(2);

+

+        lockMap.put(id, LockGrade.get(grade));

+      }

+

+      return lockMap;

+    }

+    catch (SQLException e)

+    {

+      throw new DBException(e);

+    }

+    finally

+    {

+      DBUtil.close(resultSet);

+      statementCache.releasePreparedStatement(stmt);

+    }

+  }

+

+  private void changeLocks(DBStoreAccessor accessor, String durableLockingID, LockType type,

+      Collection<? extends Object> keys, boolean on)

+  {

+    if (keys.isEmpty())

+    {

+      return;

+    }

+

+    IPreparedStatementCache statementCache = accessor.getStatementCache();

+    PreparedStatement stmtSelect = null;

+    PreparedStatement stmtInsertOrDelete = null;

+    PreparedStatement stmtUpdate = null;

+    ResultSet resultSet = null;

+

+    try

+    {

+      stmtSelect = statementCache.getPreparedStatement(sqlSelectLock, ReuseProbability.MEDIUM);

+      stmtSelect.setString(1, durableLockingID);

+

+      String sql = on ? sqlInsertLock : sqlDeleteLock;

+      stmtInsertOrDelete = statementCache.getPreparedStatement(sql, ReuseProbability.MEDIUM);

+      stmtInsertOrDelete.setString(1, durableLockingID);

+

+      stmtUpdate = statementCache.getPreparedStatement(sqlUpdateLock, ReuseProbability.MEDIUM);

+      stmtUpdate.setString(2, durableLockingID);

+

+      InternalLockManager lockManager = accessor.getStore().getRepository().getLockManager();

+      for (Object key : keys)

+      {

+        CDOID id = lockManager.getLockKeyID(key);

+        idHandler.setCDOID(stmtSelect, 2, id);

+        resultSet = stmtSelect.executeQuery();

+

+        LockGrade oldGrade = LockGrade.NONE;

+        if (resultSet.next())

+        {

+          oldGrade = LockGrade.get(resultSet.getInt(1));

+        }

+

+        LockGrade newGrade = oldGrade.getUpdated(type, on);

+        if (on && oldGrade == LockGrade.NONE)

+        {

+          idHandler.setCDOID(stmtInsertOrDelete, 2, id);

+          stmtInsertOrDelete.setInt(3, newGrade.getValue());

+          DBUtil.update(stmtInsertOrDelete, true);

+        }

+        else if (!on && newGrade == LockGrade.NONE)

+        {

+          idHandler.setCDOID(stmtInsertOrDelete, 2, id);

+          DBUtil.update(stmtInsertOrDelete, true);

+        }

+        else

+        {

+          stmtUpdate.setInt(1, newGrade.getValue());

+          idHandler.setCDOID(stmtUpdate, 3, id);

+          DBUtil.update(stmtUpdate, true);

+        }

+      }

+

+      accessor.getConnection().commit();

+    }

+    catch (SQLException e)

+    {

+      throw new DBException(e);

+    }

+    finally

+    {

+      DBUtil.close(resultSet);

+      statementCache.releasePreparedStatement(stmtUpdate);

+      statementCache.releasePreparedStatement(stmtInsertOrDelete);

+      statementCache.releasePreparedStatement(stmtSelect);

+    }

+  }

+}

diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/ExternalReferenceManager.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/ExternalReferenceManager.java
new file mode 100644
index 0000000..34b5f89
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/ExternalReferenceManager.java
@@ -0,0 +1,302 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Stefan Winkler - initial API and implementation
+ *    Stefan Winkler - bug 249610: [DB] Support external references (Implementation)
+ *    Eike Stepper - maintenance
+ */
+package org.eclipse.emf.cdo.server.internal.db;
+
+import org.eclipse.emf.cdo.common.id.CDOIDExternal;
+import org.eclipse.emf.cdo.common.id.CDOIDUtil;
+import org.eclipse.emf.cdo.common.protocol.CDODataInput;
+import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
+import org.eclipse.emf.cdo.server.IStoreAccessor;
+import org.eclipse.emf.cdo.server.StoreThreadLocal;
+import org.eclipse.emf.cdo.server.db.IDBStore;
+import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
+import org.eclipse.emf.cdo.server.db.IIDHandler;
+import org.eclipse.emf.cdo.server.db.IPreparedStatementCache;
+import org.eclipse.emf.cdo.server.db.IPreparedStatementCache.ReuseProbability;
+import org.eclipse.emf.cdo.server.internal.db.bundle.OM;
+
+import org.eclipse.net4j.db.DBException;
+import org.eclipse.net4j.db.DBType;
+import org.eclipse.net4j.db.DBUtil;
+import org.eclipse.net4j.db.ddl.IDBField;
+import org.eclipse.net4j.db.ddl.IDBIndex;
+import org.eclipse.net4j.db.ddl.IDBTable;
+import org.eclipse.net4j.util.ReflectUtil.ExcludeFromDump;
+import org.eclipse.net4j.util.lifecycle.Lifecycle;
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * @author Stefan Winkler
+ */
+public class ExternalReferenceManager extends Lifecycle
+{
+  private static final int NULL = 0;
+
+  private IDBTable table;
+
+  private IDBField idField;
+
+  private IDBField uriField;
+
+  private IDBField timestampField;
+
+  private final IIDHandler idHandler;
+
+  private AtomicLong lastMappedID = new AtomicLong(NULL);
+
+  @ExcludeFromDump
+  private transient String sqlSelectByLongID;
+
+  @ExcludeFromDump
+  private transient String sqlSelectByURI;
+
+  @ExcludeFromDump
+  private transient String sqlInsert;
+
+  public ExternalReferenceManager(IIDHandler idHandler)
+  {
+    this.idHandler = idHandler;
+  }
+
+  public IIDHandler getIDHandler()
+  {
+    return idHandler;
+  }
+
+  public long mapExternalReference(CDOIDExternal id, long commitTime)
+  {
+    IDBStoreAccessor accessor = getAccessor();
+    return mapURI(accessor, id.getURI(), commitTime);
+  }
+
+  public CDOIDExternal unmapExternalReference(long mappedId)
+  {
+    IDBStoreAccessor accessor = getAccessor();
+    return CDOIDUtil.createExternal(unmapURI(accessor, mappedId));
+  }
+
+  public long mapURI(IDBStoreAccessor accessor, String uri, long commitTime)
+  {
+    long result = lookupByURI(accessor, uri);
+    if (result < NULL)
+    {
+      // mapping found
+      return result;
+    }
+
+    return insertNew(accessor, uri, commitTime);
+  }
+
+  public String unmapURI(IDBStoreAccessor accessor, long mappedId)
+  {
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+    ResultSet resultSet = null;
+
+    try
+    {
+      stmt = statementCache.getPreparedStatement(sqlSelectByLongID, ReuseProbability.HIGH);
+      stmt.setLong(1, mappedId);
+      resultSet = stmt.executeQuery();
+
+      if (!resultSet.next())
+      {
+        OM.LOG.error("External ID " + mappedId + " not found. Database inconsistent!");
+        throw new IllegalStateException("External ID " + mappedId + " not found. Database inconsistent!");
+      }
+
+      return resultSet.getString(1);
+    }
+    catch (SQLException e)
+    {
+      throw new DBException(e);
+    }
+    finally
+    {
+      DBUtil.close(resultSet);
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  public void rawExport(Connection connection, CDODataOutput out, long fromCommitTime, long toCommitTime)
+      throws IOException
+  {
+    String where = " WHERE " + timestampField + " BETWEEN " + fromCommitTime + " AND " + toCommitTime;
+    DBUtil.serializeTable(out, connection, table, null, where);
+  }
+
+  public void rawImport(Connection connection, CDODataInput in, long fromCommitTime, long toCommitTime,
+      OMMonitor monitor) throws IOException
+  {
+    DBUtil.deserializeTable(in, connection, table, monitor);
+  }
+
+  @Override
+  protected void doActivate() throws Exception
+  {
+    super.doActivate();
+
+    IDBStore store = idHandler.getStore();
+    table = store.getDBSchema().addTable("cdo_external_refs"); //$NON-NLS-1$
+    idField = table.addField("id", idHandler.getDBType()); //$NON-NLS-1$
+    uriField = table.addField("uri", DBType.VARCHAR, 1024); //$NON-NLS-1$
+    timestampField = table.addField("committime", DBType.BIGINT); //$NON-NLS-1$
+
+    table.addIndex(IDBIndex.Type.PRIMARY_KEY, idField);
+    table.addIndex(IDBIndex.Type.NON_UNIQUE, uriField);
+
+    IDBStoreAccessor writer = store.getWriter(null);
+    Connection connection = writer.getConnection();
+    Statement statement = null;
+    ResultSet resultSet = null;
+
+    try
+    {
+      statement = connection.createStatement();
+      store.getDBAdapter().createTable(table, statement);
+      connection.commit();
+
+      String sql = "SELECT MIN(" + idField + ") FROM " + table;
+      resultSet = statement.executeQuery(sql);
+
+      if (resultSet.next())
+      {
+        lastMappedID.set(resultSet.getLong(1));
+      }
+
+      // else: resultSet is empty => table is empty
+      // and lastMappedId stays 0 - as initialized.
+    }
+    catch (SQLException ex)
+    {
+      connection.rollback();
+      throw new DBException(ex);
+    }
+    finally
+    {
+      DBUtil.close(resultSet);
+      DBUtil.close(statement);
+      writer.release();
+    }
+
+    StringBuilder builder = new StringBuilder();
+    builder.append("INSERT INTO ");
+    builder.append(table);
+    builder.append("(");
+    builder.append(idField);
+    builder.append(",");
+    builder.append(uriField);
+    builder.append(",");
+    builder.append(timestampField);
+    builder.append(") VALUES (?, ?, ?)");
+    sqlInsert = builder.toString();
+
+    builder = new StringBuilder();
+    builder.append("SELECT "); //$NON-NLS-1$
+    builder.append(idField);
+    builder.append(" FROM "); //$NON-NLS-1$
+    builder.append(table);
+    builder.append(" WHERE "); //$NON-NLS-1$
+    builder.append(uriField);
+    builder.append("=?"); //$NON-NLS-1$
+    sqlSelectByURI = builder.toString();
+
+    builder = new StringBuilder();
+    builder.append("SELECT "); //$NON-NLS-1$
+    builder.append(uriField);
+    builder.append(" FROM "); //$NON-NLS-1$
+    builder.append(table);
+    builder.append(" WHERE "); //$NON-NLS-1$
+    builder.append(idField);
+    builder.append("=?"); //$NON-NLS-1$
+    sqlSelectByLongID = builder.toString();
+  }
+
+  private long insertNew(IDBStoreAccessor accessor, String uri, long commitTime)
+  {
+    long newMappedID = lastMappedID.decrementAndGet();
+
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+
+    try
+    {
+      stmt = statementCache.getPreparedStatement(sqlInsert, ReuseProbability.MEDIUM);
+      stmt.setLong(1, newMappedID);
+      stmt.setString(2, uri);
+      stmt.setLong(3, commitTime);
+
+      DBUtil.update(stmt, true);
+      return newMappedID;
+    }
+    catch (SQLException e)
+    {
+      throw new DBException(e);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  private long lookupByURI(IDBStoreAccessor accessor, String uri)
+  {
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+    ResultSet resultSet = null;
+
+    try
+    {
+      stmt = statementCache.getPreparedStatement(sqlSelectByURI, ReuseProbability.HIGH);
+      stmt.setString(1, uri);
+
+      resultSet = stmt.executeQuery();
+
+      if (resultSet.next())
+      {
+        return resultSet.getLong(1);
+      }
+
+      // Not found ...
+      return NULL;
+    }
+    catch (SQLException e)
+    {
+      throw new DBException(e);
+    }
+    finally
+    {
+      DBUtil.close(resultSet);
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  private static IDBStoreAccessor getAccessor()
+  {
+    IStoreAccessor accessor = StoreThreadLocal.getAccessor();
+    if (accessor == null)
+    {
+      throw new IllegalStateException("Can only be called from within a valid IDBStoreAccessor context");
+    }
+
+    return (IDBStoreAccessor)accessor;
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/IObjectTypeMapper.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/IObjectTypeMapper.java
new file mode 100644
index 0000000..49344d3
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/IObjectTypeMapper.java
@@ -0,0 +1,53 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - 271444: [DB] Multiple refactorings bug 271444
+ */
+package org.eclipse.emf.cdo.server.internal.db;
+
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.model.CDOClassifierRef;
+import org.eclipse.emf.cdo.common.protocol.CDODataInput;
+import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
+import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
+import org.eclipse.emf.cdo.server.db.IIDHandler;
+
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+
+import org.eclipse.emf.ecore.EClass;
+
+import java.io.IOException;
+import java.sql.Connection;
+
+/**
+ * @author Eike Stepper
+ * @since 4.0
+ */
+public interface IObjectTypeMapper
+{
+  public CDOClassifierRef getObjectType(IDBStoreAccessor accessor, CDOID id);
+
+  public void putObjectType(IDBStoreAccessor accessor, long timeStamp, CDOID id, EClass type);
+
+  public void removeObjectType(IDBStoreAccessor accessor, CDOID id);
+
+  /**
+   * Return the maximum object id managed by this cache.
+   * 
+   * @param connection
+   *          the DB connection to use.
+   * @return the maximum object ID.
+   */
+  public CDOID getMaxID(Connection connection, IIDHandler idHandler);
+
+  public void rawExport(Connection connection, CDODataOutput out, long fromCommitTime, long toCommitTime)
+      throws IOException;
+
+  public void rawImport(Connection connection, CDODataInput in, OMMonitor monitor) throws IOException;
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/LongIDHandler.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/LongIDHandler.java
new file mode 100644
index 0000000..79d0615
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/LongIDHandler.java
@@ -0,0 +1,265 @@
+/**

+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    Eike Stepper - initial API and implementation

+ */

+package org.eclipse.emf.cdo.server.internal.db;

+

+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;

+import org.eclipse.emf.cdo.common.id.CDOID;

+import org.eclipse.emf.cdo.common.id.CDOID.ObjectType;

+import org.eclipse.emf.cdo.common.id.CDOIDExternal;

+import org.eclipse.emf.cdo.common.id.CDOIDUtil;

+import org.eclipse.emf.cdo.common.protocol.CDODataInput;

+import org.eclipse.emf.cdo.common.protocol.CDODataOutput;

+import org.eclipse.emf.cdo.common.revision.CDORevision;

+import org.eclipse.emf.cdo.server.IStoreAccessor.CommitContext;

+import org.eclipse.emf.cdo.server.StoreThreadLocal;

+import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;

+import org.eclipse.emf.cdo.server.db.IIDHandler;

+import org.eclipse.emf.cdo.server.db.mapping.ITypeMapping;

+import org.eclipse.emf.cdo.server.internal.db.mapping.CoreTypeMappings;

+import org.eclipse.emf.cdo.spi.server.LongIDStore;

+

+import org.eclipse.net4j.db.DBType;

+import org.eclipse.net4j.util.lifecycle.Lifecycle;

+import org.eclipse.net4j.util.om.monitor.OMMonitor;

+

+import java.io.IOException;

+import java.sql.Connection;

+import java.sql.PreparedStatement;

+import java.sql.ResultSet;

+import java.sql.SQLException;

+import java.util.Set;

+

+/**

+ * @author Eike Stepper

+ */

+public class LongIDHandler extends Lifecycle implements IIDHandler

+{

+  public static final CDOID MIN = CDOID.NULL;

+

+  public static final CDOID MAX = create(Long.MAX_VALUE);

+

+  private DBStore store;

+

+  private ExternalReferenceManager externalReferenceManager;

+

+  private CDOID lastObjectID = MIN;

+

+  private CDOID nextLocalObjectID = MAX;

+

+  public LongIDHandler(DBStore store)

+  {

+    this.store = store;

+    externalReferenceManager = new ExternalReferenceManager(this);

+  }

+

+  public DBStore getStore()

+  {

+    return store;

+  }

+

+  public Set<ObjectType> getObjectIDTypes()

+  {

+    return LongIDStore.OBJECT_ID_TYPES;

+  }

+

+  public CDOID getMinCDOID()

+  {

+    return MIN;

+  }

+

+  public CDOID getMaxCDOID()

+  {

+    return MAX;

+  }

+

+  public int compare(CDOID id1, CDOID id2)

+  {

+    return id1.compareTo(id2);

+  }

+

+  public CDOID createCDOID(String val)

+  {

+    Long id = Long.valueOf(val);

+    return create(id);

+  }

+

+  public synchronized CDOID getLastObjectID()

+  {

+    return lastObjectID;

+  }

+

+  public synchronized void setLastObjectID(CDOID lastObjectID)

+  {

+    this.lastObjectID = lastObjectID;

+  }

+

+  public synchronized void adjustLastObjectID(CDOID maxID)

+  {

+    if (compare(maxID, lastObjectID) > 0)

+    {

+      lastObjectID = maxID;

+    }

+  }

+

+  public synchronized CDOID getNextLocalObjectID()

+  {

+    return nextLocalObjectID;

+  }

+

+  public synchronized void setNextLocalObjectID(CDOID nextLocalObjectID)

+  {

+    this.nextLocalObjectID = nextLocalObjectID;

+  }

+

+  public synchronized CDOID getNextCDOID(CDORevision revision)

+  {

+    if (revision.getBranch().isLocal())

+    {

+      CDOID result = nextLocalObjectID;

+      nextLocalObjectID = create(value(result) - 1);

+      return result;

+    }

+

+    lastObjectID = create(value(lastObjectID) + 1);

+    return lastObjectID;

+  }

+

+  public boolean isLocalCDOID(CDOID id)

+  {

+    return compare(id, nextLocalObjectID) > 0;

+  }

+

+  public DBType getDBType()

+  {

+    return DBType.BIGINT;

+  }

+

+  public ITypeMapping getObjectTypeMapping()

+  {

+    return new CoreTypeMappings.TMObject();

+  }

+

+  public void appendCDOID(StringBuilder builder, CDOID id)

+  {

+    long value = value(id);

+    builder.append(value);

+  }

+

+  public void setCDOID(PreparedStatement stmt, int column, CDOID id) throws SQLException

+  {

+    setCDOID(stmt, column, id, CDOBranchPoint.INVALID_DATE);

+  }

+

+  public void setCDOID(PreparedStatement stmt, int column, CDOID id, long commitTime) throws SQLException

+  {

+    long value;

+    if (id.getType() == CDOID.Type.EXTERNAL_OBJECT)

+    {

+      if (commitTime == CDOBranchPoint.INVALID_DATE)

+      {

+        CommitContext commitContext = StoreThreadLocal.getCommitContext();

+        commitTime = commitContext != null ? commitContext.getBranchPoint().getTimeStamp()

+            : CDOBranchPoint.UNSPECIFIED_DATE; // Happens on rawStore for workspace checkouts

+      }

+

+      value = externalReferenceManager.mapExternalReference((CDOIDExternal)id, commitTime);

+    }

+    else

+    {

+      value = value(id);

+    }

+

+    stmt.setLong(column, value);

+  }

+

+  public CDOID getCDOID(ResultSet resultSet, int column) throws SQLException

+  {

+    long id = resultSet.getLong(column);

+    if (resultSet.wasNull())

+    {

+      return null;

+    }

+

+    return unmapExternalReference(id);

+  }

+

+  public CDOID getCDOID(ResultSet resultSet, String name) throws SQLException

+  {

+    long id = resultSet.getLong(name);

+    if (resultSet.wasNull())

+    {

+      return null;

+    }

+

+    return unmapExternalReference(id);

+  }

+

+  private CDOID unmapExternalReference(long id)

+  {

+    if (id < 0)

+    {

+      return externalReferenceManager.unmapExternalReference(id);

+    }

+

+    return create(id);

+  }

+

+  public CDOID mapURI(IDBStoreAccessor accessor, String uri, long commitTime)

+  {

+    return create(externalReferenceManager.mapURI(accessor, uri, commitTime));

+  }

+

+  public String unmapURI(IDBStoreAccessor accessor, CDOID id)

+  {

+    if (id.getType() == CDOID.Type.EXTERNAL_OBJECT)

+    {

+      return ((CDOIDExternal)id).getURI();

+    }

+

+    return externalReferenceManager.unmapURI(accessor, value(id));

+  }

+

+  public void rawExport(Connection connection, CDODataOutput out, long fromCommitTime, long toCommitTime)

+      throws IOException

+  {

+    externalReferenceManager.rawExport(connection, out, fromCommitTime, toCommitTime);

+  }

+

+  public void rawImport(Connection connection, CDODataInput in, long fromCommitTime, long toCommitTime,

+      OMMonitor monitor) throws IOException

+  {

+    externalReferenceManager.rawImport(connection, in, fromCommitTime, toCommitTime, monitor);

+  }

+

+  @Override

+  protected void doActivate() throws Exception

+  {

+    super.doActivate();

+    externalReferenceManager.activate();

+  }

+

+  @Override

+  protected void doDeactivate() throws Exception

+  {

+    externalReferenceManager.deactivate();

+    super.doDeactivate();

+  }

+

+  private static CDOID create(long id)

+  {

+    return CDOIDUtil.createLong(id);

+  }

+

+  private static long value(CDOID id)

+  {

+    return CDOIDUtil.getLong(id);

+  }

+}

diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/MetaDataManager.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/MetaDataManager.java
new file mode 100644
index 0000000..8882555
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/MetaDataManager.java
@@ -0,0 +1,429 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - bug 271444: [DB] Multiple refactorings
+ *    Kai Schlamp - bug 282976: [DB] Influence Mappings through EAnnotations
+ *    Stefan Winkler - bug 282976: [DB] Influence Mappings through EAnnotations
+ */
+package org.eclipse.emf.cdo.server.internal.db;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.model.CDOModelConstants;
+import org.eclipse.emf.cdo.common.model.CDOModelUtil;
+import org.eclipse.emf.cdo.common.model.CDOPackageUnit;
+import org.eclipse.emf.cdo.common.model.EMFUtil;
+import org.eclipse.emf.cdo.common.protocol.CDODataInput;
+import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
+import org.eclipse.emf.cdo.server.StoreThreadLocal;
+import org.eclipse.emf.cdo.server.db.IDBStore;
+import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
+import org.eclipse.emf.cdo.server.db.IMetaDataManager;
+import org.eclipse.emf.cdo.server.internal.db.bundle.OM;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageInfo;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit;
+
+import org.eclipse.net4j.db.DBException;
+import org.eclipse.net4j.db.DBUtil;
+import org.eclipse.net4j.db.IDBRowHandler;
+import org.eclipse.net4j.util.lifecycle.Lifecycle;
+import org.eclipse.net4j.util.om.monitor.Monitor;
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+import org.eclipse.net4j.util.om.monitor.OMMonitor.Async;
+import org.eclipse.net4j.util.om.trace.ContextTracer;
+
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EModelElement;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+/**
+ * @author Eike Stepper
+ */
+public class MetaDataManager extends Lifecycle implements IMetaDataManager
+{
+  private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG, MetaDataManager.class);
+
+  private static final boolean ZIP_PACKAGE_BYTES = true;
+
+  private IDBStore store;
+
+  private Map<EModelElement, CDOID> modelElementToMetaID = new HashMap<EModelElement, CDOID>();
+
+  private Map<CDOID, EModelElement> metaIDToModelElement = new HashMap<CDOID, EModelElement>();
+
+  public MetaDataManager(IDBStore store)
+  {
+    this.store = store;
+  }
+
+  public synchronized CDOID getMetaID(EModelElement modelElement, long commitTime)
+  {
+    CDOID metaID = modelElementToMetaID.get(modelElement);
+    if (metaID != null)
+    {
+      return metaID;
+    }
+
+    IDBStoreAccessor accessor = (IDBStoreAccessor)StoreThreadLocal.getAccessor();
+    String uri = EcoreUtil.getURI(modelElement).toString();
+    metaID = store.getIDHandler().mapURI(accessor, uri, commitTime);
+    cacheMetaIDMapping(modelElement, metaID);
+
+    return metaID;
+  }
+
+  public synchronized EModelElement getMetaInstance(CDOID id)
+  {
+    EModelElement modelElement = metaIDToModelElement.get(id);
+    if (modelElement != null)
+    {
+      return modelElement;
+    }
+
+    IDBStoreAccessor accessor = (IDBStoreAccessor)StoreThreadLocal.getAccessor();
+    String uri = store.getIDHandler().unmapURI(accessor, id);
+
+    ResourceSet resourceSet = new ResourceSetImpl();
+    resourceSet.setPackageRegistry(getStore().getRepository().getPackageRegistry());
+
+    return (EModelElement)resourceSet.getEObject(URI.createURI(uri), true);
+  }
+
+  public synchronized void clearMetaIDMappings()
+  {
+    modelElementToMetaID.clear();
+    metaIDToModelElement.clear();
+  }
+
+  public final EPackage[] loadPackageUnit(Connection connection, InternalCDOPackageUnit packageUnit)
+  {
+    String where = CDODBSchema.PACKAGE_UNITS_ID.getName() + "='" + packageUnit.getID() + "'"; //$NON-NLS-1$ //$NON-NLS-2$
+    Object[] values = DBUtil.select(connection, where, CDODBSchema.PACKAGE_UNITS_PACKAGE_DATA);
+    byte[] bytes = (byte[])values[0];
+    EPackage ePackage = createEPackage(packageUnit, bytes);
+    return EMFUtil.getAllPackages(ePackage);
+  }
+
+  public Collection<InternalCDOPackageUnit> readPackageUnits(Connection connection)
+  {
+    return readPackageUnits(connection, CDOBranchPoint.UNSPECIFIED_DATE, CDOBranchPoint.UNSPECIFIED_DATE, new Monitor());
+  }
+
+  public final void writePackageUnits(Connection connection, InternalCDOPackageUnit[] packageUnits, OMMonitor monitor)
+  {
+    try
+    {
+      monitor.begin(2);
+      fillSystemTables(connection, packageUnits, monitor.fork());
+    }
+    finally
+    {
+      monitor.done();
+    }
+  }
+
+  public void rawExport(Connection connection, CDODataOutput out, long fromCommitTime, long toCommitTime)
+      throws IOException
+  {
+    // Export package units
+    String where = " WHERE p_u." + CDODBSchema.PACKAGE_UNITS_ID + "<>'" + CDOModelConstants.CORE_PACKAGE_URI + //
+        "' AND p_u." + CDODBSchema.PACKAGE_UNITS_ID + "<>'" + CDOModelConstants.RESOURCE_PACKAGE_URI + //
+        "' AND p_u." + CDODBSchema.PACKAGE_UNITS_ID + "<>'" + CDOModelConstants.TYPES_PACKAGE_URI + //
+        "' AND p_u." + CDODBSchema.PACKAGE_UNITS_TIME_STAMP + " BETWEEN " + fromCommitTime + " AND " + toCommitTime;
+    DBUtil.serializeTable(out, connection, CDODBSchema.PACKAGE_UNITS, "p_u", where);
+
+    // Export package infos
+    String join = ", " + CDODBSchema.PACKAGE_UNITS + " p_u" + where + " AND p_i." + CDODBSchema.PACKAGE_INFOS_UNIT
+        + "=p_u." + CDODBSchema.PACKAGE_UNITS_ID;
+    DBUtil.serializeTable(out, connection, CDODBSchema.PACKAGE_INFOS, "p_i", join);
+  }
+
+  public Collection<InternalCDOPackageUnit> rawImport(Connection connection, CDODataInput in, long fromCommitTime,
+      long toCommitTime, OMMonitor monitor) throws IOException
+  {
+    monitor.begin(3);
+
+    try
+    {
+      DBUtil.deserializeTable(in, connection, CDODBSchema.PACKAGE_UNITS, monitor.fork());
+      DBUtil.deserializeTable(in, connection, CDODBSchema.PACKAGE_INFOS, monitor.fork());
+      return readPackageUnits(connection, fromCommitTime, toCommitTime, monitor.fork());
+    }
+    finally
+    {
+      monitor.done();
+    }
+  }
+
+  protected IDBStore getStore()
+  {
+    return store;
+  }
+
+  @Override
+  protected void doBeforeActivate() throws Exception
+  {
+    checkState(store, "Store is not set"); //$NON-NLS-1$
+  }
+
+  @Override
+  protected void doDeactivate() throws Exception
+  {
+    clearMetaIDMappings();
+    super.doDeactivate();
+  }
+
+  protected InternalCDOPackageInfo createPackageInfo()
+  {
+    return (InternalCDOPackageInfo)CDOModelUtil.createPackageInfo();
+  }
+
+  protected InternalCDOPackageUnit createPackageUnit()
+  {
+    return (InternalCDOPackageUnit)CDOModelUtil.createPackageUnit();
+  }
+
+  private InternalCDOPackageRegistry getPackageRegistry()
+  {
+    return (InternalCDOPackageRegistry)store.getRepository().getPackageRegistry();
+  }
+
+  private EPackage createEPackage(InternalCDOPackageUnit packageUnit, byte[] bytes)
+  {
+    ResourceSet resourceSet = EMFUtil.newEcoreResourceSet(getPackageRegistry());
+    return EMFUtil.createEPackage(packageUnit.getID(), bytes, ZIP_PACKAGE_BYTES, resourceSet, false);
+  }
+
+  private byte[] getEPackageBytes(InternalCDOPackageUnit packageUnit)
+  {
+    EPackage ePackage = packageUnit.getTopLevelPackageInfo().getEPackage();
+    return EMFUtil.getEPackageBytes(ePackage, ZIP_PACKAGE_BYTES, getPackageRegistry());
+  }
+
+  private void fillSystemTables(Connection connection, InternalCDOPackageUnit packageUnit, OMMonitor monitor)
+  {
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Writing package unit: {0}", packageUnit); //$NON-NLS-1$
+    }
+
+    InternalCDOPackageInfo[] packageInfos = packageUnit.getPackageInfos();
+    Async async = null;
+    monitor.begin(1 + packageInfos.length);
+
+    try
+    {
+      String sql = "INSERT INTO " + CDODBSchema.PACKAGE_UNITS + " VALUES (?, ?, ?, ?)"; //$NON-NLS-1$ //$NON-NLS-2$
+      DBUtil.trace(sql);
+      PreparedStatement stmt = null;
+
+      try
+      {
+        async = monitor.forkAsync();
+        stmt = connection.prepareStatement(sql);
+        stmt.setString(1, packageUnit.getID());
+        stmt.setInt(2, packageUnit.getOriginalType().ordinal());
+        stmt.setLong(3, packageUnit.getTimeStamp());
+        stmt.setBytes(4, getEPackageBytes(packageUnit));
+
+        if (stmt.execute())
+        {
+          throw new DBException("No result set expected"); //$NON-NLS-1$
+        }
+
+        if (stmt.getUpdateCount() == 0)
+        {
+          throw new DBException("No row inserted into table " + CDODBSchema.PACKAGE_UNITS); //$NON-NLS-1$
+        }
+      }
+      catch (SQLException ex)
+      {
+        throw new DBException(ex);
+      }
+      finally
+      {
+        DBUtil.close(stmt);
+        if (async != null)
+        {
+          async.stop();
+        }
+      }
+
+      for (InternalCDOPackageInfo packageInfo : packageInfos)
+      {
+        fillSystemTables(connection, packageInfo, monitor); // Don't fork monitor
+      }
+    }
+    finally
+    {
+      monitor.done();
+    }
+  }
+
+  private void fillSystemTables(Connection connection, InternalCDOPackageUnit[] packageUnits, OMMonitor monitor)
+  {
+    try
+    {
+      monitor.begin(packageUnits.length);
+      for (InternalCDOPackageUnit packageUnit : packageUnits)
+      {
+        fillSystemTables(connection, packageUnit, monitor.fork());
+      }
+    }
+    finally
+    {
+      monitor.done();
+    }
+  }
+
+  private void fillSystemTables(Connection connection, InternalCDOPackageInfo packageInfo, OMMonitor monitor)
+  {
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Writing package info: {0}", packageInfo); //$NON-NLS-1$
+    }
+
+    String packageURI = packageInfo.getPackageURI();
+    String parentURI = packageInfo.getParentURI();
+    String unitID = packageInfo.getPackageUnit().getID();
+
+    String sql = "INSERT INTO " + CDODBSchema.PACKAGE_INFOS + " VALUES (?, ?, ?)"; //$NON-NLS-1$ //$NON-NLS-2$
+    DBUtil.trace(sql);
+    PreparedStatement stmt = null;
+    Async async = monitor.forkAsync();
+
+    try
+    {
+      stmt = connection.prepareStatement(sql);
+      stmt.setString(1, packageURI);
+      stmt.setString(2, parentURI);
+      stmt.setString(3, unitID);
+
+      if (stmt.execute())
+      {
+        throw new DBException("No result set expected"); //$NON-NLS-1$
+      }
+
+      if (stmt.getUpdateCount() == 0)
+      {
+        throw new DBException("No row inserted into table " + CDODBSchema.PACKAGE_INFOS); //$NON-NLS-1$
+      }
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex);
+    }
+    finally
+    {
+      DBUtil.close(stmt);
+      if (async != null)
+      {
+        async.stop();
+      }
+    }
+  }
+
+  private Collection<InternalCDOPackageUnit> readPackageUnits(Connection connection, long fromCommitTime,
+      long toCommitTime, OMMonitor monitor)
+  {
+    final Map<String, InternalCDOPackageUnit> packageUnits = new HashMap<String, InternalCDOPackageUnit>();
+    IDBRowHandler unitRowHandler = new IDBRowHandler()
+    {
+      public boolean handle(int row, final Object... values)
+      {
+        InternalCDOPackageUnit packageUnit = createPackageUnit();
+        packageUnit.setOriginalType(CDOPackageUnit.Type.values()[(Integer)values[1]]);
+        packageUnit.setTimeStamp((Long)values[2]);
+        packageUnits.put((String)values[0], packageUnit);
+        return true;
+      }
+    };
+
+    String where = null;
+    if (fromCommitTime != CDOBranchPoint.UNSPECIFIED_DATE)
+    {
+      where = CDODBSchema.PACKAGE_UNITS_ID + "<>'" + CDOModelConstants.CORE_PACKAGE_URI + "' AND "
+          + CDODBSchema.PACKAGE_UNITS_ID + "<>'" + CDOModelConstants.RESOURCE_PACKAGE_URI + "' AND "
+          + CDODBSchema.PACKAGE_UNITS_ID + "<>'" + CDOModelConstants.TYPES_PACKAGE_URI + "' AND "
+          + CDODBSchema.PACKAGE_UNITS_TIME_STAMP + " BETWEEN " + fromCommitTime + " AND " + toCommitTime;
+    }
+
+    DBUtil.select(connection, unitRowHandler, where, CDODBSchema.PACKAGE_UNITS_ID,
+        CDODBSchema.PACKAGE_UNITS_ORIGINAL_TYPE, CDODBSchema.PACKAGE_UNITS_TIME_STAMP);
+
+    final Map<String, List<InternalCDOPackageInfo>> packageInfos = new HashMap<String, List<InternalCDOPackageInfo>>();
+    IDBRowHandler infoRowHandler = new IDBRowHandler()
+    {
+      public boolean handle(int row, final Object... values)
+      {
+        InternalCDOPackageInfo packageInfo = createPackageInfo();
+        packageInfo.setPackageURI((String)values[1]);
+        packageInfo.setParentURI((String)values[2]);
+
+        String unit = (String)values[0];
+        List<InternalCDOPackageInfo> list = packageInfos.get(unit);
+        if (list == null)
+        {
+          list = new ArrayList<InternalCDOPackageInfo>();
+          packageInfos.put(unit, list);
+        }
+
+        list.add(packageInfo);
+        return true;
+      }
+    };
+
+    monitor.begin();
+    Async async = monitor.forkAsync();
+
+    try
+    {
+      DBUtil.select(connection, infoRowHandler, CDODBSchema.PACKAGE_INFOS_UNIT, CDODBSchema.PACKAGE_INFOS_URI,
+          CDODBSchema.PACKAGE_INFOS_PARENT);
+    }
+    finally
+    {
+      async.stop();
+      monitor.done();
+    }
+
+    for (Entry<String, InternalCDOPackageUnit> entry : packageUnits.entrySet())
+    {
+      String id = entry.getKey();
+      InternalCDOPackageUnit packageUnit = entry.getValue();
+
+      List<InternalCDOPackageInfo> list = packageInfos.get(id);
+      InternalCDOPackageInfo[] array = list.toArray(new InternalCDOPackageInfo[list.size()]);
+      packageUnit.setPackageInfos(array);
+    }
+
+    return packageUnits.values();
+  }
+
+  private void cacheMetaIDMapping(EModelElement modelElement, CDOID metaID)
+  {
+    modelElementToMetaID.put(modelElement, metaID);
+    metaIDToModelElement.put(metaID, modelElement);
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/NullPreparedStatementCache.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/NullPreparedStatementCache.java
new file mode 100644
index 0000000..86f1894
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/NullPreparedStatementCache.java
@@ -0,0 +1,69 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - 271444: [DB] Multiple refactorings bug 271444
+ */
+package org.eclipse.emf.cdo.server.internal.db;
+
+import org.eclipse.emf.cdo.server.internal.db.bundle.OM;
+
+import org.eclipse.net4j.db.DBException;
+import org.eclipse.net4j.db.DBUtil;
+
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.HashSet;
+
+/**
+ * @author Stefan Winkler
+ * @since 2.0
+ */
+public class NullPreparedStatementCache extends AbstractPreparedStatementCache
+{
+  private HashSet<PreparedStatement> allocatedStatements = new HashSet<PreparedStatement>();
+
+  public NullPreparedStatementCache()
+  {
+  }
+
+  public PreparedStatement getPreparedStatement(String sql, ReuseProbability reuseProbability)
+  {
+    try
+    {
+      PreparedStatement result = getConnection().prepareStatement(sql);
+      allocatedStatements.add(result);
+      return result;
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex);
+    }
+  }
+
+  public void releasePreparedStatement(PreparedStatement ps)
+  {
+    allocatedStatements.remove(ps);
+    DBUtil.close(ps);
+  }
+
+  @Override
+  protected void doBeforeDeactivate() throws Exception
+  {
+    if (!allocatedStatements.isEmpty())
+    {
+      OM.LOG.warn("Possible Leak Detected:"); //$NON-NLS-1$
+      for (PreparedStatement ps : allocatedStatements)
+      {
+        OM.LOG.warn("- " + ps.toString()); //$NON-NLS-1$
+      }
+
+      assert false;
+    }
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/ObjectIDIterator.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/ObjectIDIterator.java
new file mode 100644
index 0000000..9328e5c
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/ObjectIDIterator.java
@@ -0,0 +1,138 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Victor Roldan Betancort - bug 208689
+ */
+package org.eclipse.emf.cdo.server.internal.db;
+
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
+import org.eclipse.emf.cdo.server.db.IIDHandler;
+import org.eclipse.emf.cdo.server.db.mapping.IMappingStrategy;
+
+import org.eclipse.net4j.db.DBException;
+import org.eclipse.net4j.db.DBUtil;
+import org.eclipse.net4j.util.collection.CloseableIterator;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.NoSuchElementException;
+
+/**
+ * @author Eike Stepper
+ */
+public abstract class ObjectIDIterator implements CloseableIterator<CDOID>
+{
+  private IMappingStrategy mappingStrategy;
+
+  private IIDHandler idHandler;
+
+  private IDBStoreAccessor accessor;
+
+  private ResultSet currentResultSet;
+
+  private CDOID nextID;
+
+  private boolean closed;
+
+  /**
+   * Creates an iterator over all objects in a store. It is important to {@link #close()} of this iterator after usage
+   * to properly close internal result sets.
+   */
+  public ObjectIDIterator(IMappingStrategy mappingStrategy, IDBStoreAccessor accessor)
+  {
+    this.mappingStrategy = mappingStrategy;
+    this.accessor = accessor;
+    idHandler = getMappingStrategy().getStore().getIDHandler();
+
+  }
+
+  public void close()
+  {
+    closeCurrentResultSet();
+    nextID = null;
+    closed = true;
+  }
+
+  public boolean isClosed()
+  {
+    return closed;
+  }
+
+  public IMappingStrategy getMappingStrategy()
+  {
+    return mappingStrategy;
+  }
+
+  public IDBStoreAccessor getAccessor()
+  {
+    return accessor;
+  }
+
+  public boolean hasNext()
+  {
+    if (closed)
+    {
+      return false;
+    }
+
+    nextID = null;
+    for (;;)
+    {
+      if (currentResultSet == null)
+      {
+        currentResultSet = getNextResultSet();
+        if (currentResultSet == null)
+        {
+          return false;
+        }
+      }
+
+      try
+      {
+        if (currentResultSet.next())
+        {
+          nextID = idHandler.getCDOID(currentResultSet, 1);
+          return true;
+        }
+
+        closeCurrentResultSet();
+
+        currentResultSet = null;
+        return false;
+      }
+      catch (SQLException ex)
+      {
+        throw new DBException(ex);
+      }
+    }
+  }
+
+  protected void closeCurrentResultSet()
+  {
+    DBUtil.close(currentResultSet);
+  }
+
+  public CDOID next()
+  {
+    if (nextID == null)
+    {
+      throw new NoSuchElementException();
+    }
+
+    return nextID;
+  }
+
+  public void remove()
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  protected abstract ResultSet getNextResultSet();
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/SQLQueryHandler.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/SQLQueryHandler.java
new file mode 100644
index 0000000..589e7a1
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/SQLQueryHandler.java
@@ -0,0 +1,364 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kai Schlamp - initial API and implementation
+ *    Eike Stepper - maintenance
+ *    Kai Schlamp - Bug 284812: [DB] Query non CDO object fails
+ *    Erdal Karaca - added cdoObjectResultAsMap parameter to return Map<String,Object> in result
+ */
+package org.eclipse.emf.cdo.server.internal.db;
+
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.util.CDOQueryInfo;
+import org.eclipse.emf.cdo.server.IQueryContext;
+import org.eclipse.emf.cdo.server.IQueryHandler;
+import org.eclipse.emf.cdo.server.db.IIDHandler;
+
+import org.eclipse.net4j.db.DBException;
+import org.eclipse.net4j.db.DBUtil;
+
+import java.sql.Clob;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Implements server side SQL query execution.
+ * 
+ * @author Kai Schlamp
+ */
+public class SQLQueryHandler implements IQueryHandler
+{
+  public static final String QUERY_LANGUAGE = "sql";
+
+  public static final String FIRST_RESULT = "firstResult";
+
+  public static final String CDO_OBJECT_QUERY = "cdoObjectQuery";
+
+  public static final String MAP_QUERY = "mapQuery";
+
+  public static final String QUERY_STATEMENT = "queryStatement";
+
+  private DBStoreAccessor storeAccessor;
+
+  public SQLQueryHandler(DBStoreAccessor storeAccessor)
+  {
+    this.storeAccessor = storeAccessor;
+  }
+
+  public DBStoreAccessor getStoreAccessor()
+  {
+    return storeAccessor;
+  }
+
+  /**
+   * Executes SQL queries. Gets the connection from {@link DBStoreAccessor}, creates a SQL query and sets the parameters
+   * taken from the {@link CDOQueryInfo#getParameters()}.
+   * <p>
+   * Takes into account the {@link CDOQueryInfo#getMaxResults()} and the {@link SQLQueryHandler#FIRST_RESULT} (numbered
+   * from 0) values for paging.
+   * <p>
+   * By default (parameter {@link SQLQueryHandler#CDO_OBJECT_QUERY} == true) a query for CDO Objects is exectued. The
+   * SQL query must return the CDO ID in the first column for this to work. If you set
+   * {@link SQLQueryHandler#CDO_OBJECT_QUERY} parameter to false, the value of the first column of a row itself is
+   * returned.
+   * <p>
+   * By default (parameter {@link SQLQueryHandler#QUERY_STATEMENT} == true) query statements are executed. Set this
+   * parameter to false for update/DDL statements.
+   * <p>
+   * It is possible to use variables inside the SQL string with ":" as prefix. E.g.
+   * "SELECT cdo_id FROM Company WHERE name LIKE :name". The value must then be set by using a parameter. E.g.
+   * query.setParameter(":name", "Foo%");
+   * 
+   * @param info
+   *          the object containing the query and parameters
+   * @param context
+   *          the query results are placed in the context
+   * @see IQueryHandler#executeQuery(CDOQueryInfo, IQueryContext)
+   */
+  public void executeQuery(CDOQueryInfo info, IQueryContext context)
+  {
+    String language = info.getQueryLanguage();
+    if (!QUERY_LANGUAGE.equals(language))
+    {
+      throw new IllegalArgumentException("Unsupported query language: " + language);
+    }
+
+    IIDHandler idHandler = storeAccessor.getStore().getIDHandler();
+    Connection connection = storeAccessor.getConnection();
+    PreparedStatement statement = null;
+    ResultSet resultSet = null;
+    String query = info.getQueryString();
+
+    try
+    {
+      int firstResult = -1;
+      boolean queryStatement = true;
+      boolean objectQuery = true;
+      boolean mapQuery = false;
+
+      HashMap<String, List<Integer>> paramMap = new HashMap<String, List<Integer>>();
+      query = parse(query, paramMap);
+      statement = connection.prepareStatement(query, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
+
+      for (String key : info.getParameters().keySet())
+      {
+        if (FIRST_RESULT.equalsIgnoreCase(key))
+        {
+          final Object o = info.getParameters().get(key);
+          if (o != null)
+          {
+            try
+            {
+              firstResult = (Integer)o;
+            }
+            catch (ClassCastException ex)
+            {
+              throw new IllegalArgumentException("Parameter " + FIRST_RESULT + " must be an integer but it is a " + o
+                  + " class " + o.getClass().getName(), ex);
+            }
+          }
+        }
+        else if (QUERY_STATEMENT.equalsIgnoreCase(key))
+        {
+          final Object o = info.getParameters().get(key);
+          if (o != null)
+          {
+            try
+            {
+              queryStatement = (Boolean)o;
+            }
+            catch (ClassCastException ex)
+            {
+              throw new IllegalArgumentException("Parameter " + QUERY_STATEMENT + " must be an boolean but it is a "
+                  + o + " class " + o.getClass().getName(), ex);
+            }
+          }
+        }
+        else if (CDO_OBJECT_QUERY.equalsIgnoreCase(key))
+        {
+          final Object o = info.getParameters().get(key);
+          if (o != null)
+          {
+            try
+            {
+              objectQuery = (Boolean)o;
+            }
+            catch (ClassCastException ex)
+            {
+              throw new IllegalArgumentException("Parameter " + CDO_OBJECT_QUERY + " must be a boolean but it is a "
+                  + o + " class " + o.getClass().getName(), ex);
+            }
+          }
+        }
+        else if (MAP_QUERY.equalsIgnoreCase(key))
+        {
+          final Object o = info.getParameters().get(key);
+          if (o != null)
+          {
+            try
+            {
+              mapQuery = (Boolean)o;
+            }
+            catch (ClassCastException ex)
+            {
+              throw new IllegalArgumentException("Parameter " + MAP_QUERY + " must be a boolean but it is a " + o
+                  + " class " + o.getClass().getName(), ex);
+            }
+          }
+        }
+        else
+        {
+          if (!paramMap.containsKey(key) || paramMap.get(key) == null)
+          {
+            throw new IllegalArgumentException("No parameter value found for named parameter " + key);
+          }
+
+          Integer[] indexes = paramMap.get(key).toArray(new Integer[0]);
+          for (int i = 0; i < indexes.length; i++)
+          {
+            Object parameter = info.getParameters().get(key);
+            statement.setObject(indexes[i], parameter);
+          }
+        }
+      }
+
+      if (queryStatement)
+      {
+        resultSet = statement.executeQuery();
+        if (firstResult > -1)
+        {
+          resultSet.absolute(firstResult);
+        }
+
+        String[] columnNames = null;
+        if (mapQuery)
+        {
+          columnNames = new String[resultSet.getMetaData().getColumnCount()];
+          for (int i = 1; i <= columnNames.length; i++)
+          {
+            columnNames[i - 1] = resultSet.getMetaData().getColumnName(i);
+          }
+        }
+
+        int maxResults = info.getMaxResults();
+        int counter = 0;
+
+        while (resultSet.next())
+        {
+          if (maxResults != CDOQueryInfo.UNLIMITED_RESULTS && counter++ >= maxResults)
+          {
+            break;
+          }
+
+          if (objectQuery)
+          {
+            CDOID result = idHandler.getCDOID(resultSet, 1);
+            context.addResult(result);
+          }
+          else
+          {
+            int columnCount = resultSet.getMetaData().getColumnCount();
+            if (columnCount == 1)
+            {
+              Object result = convertValue(resultSet.getObject(1));
+              context.addResult(mapQuery ? toMap(columnNames, new Object[] { result }) : result);
+            }
+            else
+            {
+              Object[] results = new Object[columnCount];
+              for (int i = 0; i < columnCount; i++)
+              {
+                results[i] = convertValue(resultSet.getObject(i + 1));
+              }
+
+              context.addResult(mapQuery ? toMap(columnNames, results) : results);
+            }
+          }
+        }
+      }
+      else
+      {
+        int result = statement.executeUpdate();
+        context.addResult(result);
+      }
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException("Problem while executing SQL query: " + query, ex);
+    }
+    finally
+    {
+      DBUtil.close(resultSet);
+      DBUtil.close(statement);
+    }
+  }
+
+  private Object convertValue(Object value)
+  {
+    if (value instanceof Clob)
+    {
+      Clob clob = (Clob)value;
+
+      try
+      {
+        value = clob.getSubString(1, (int)clob.length());
+      }
+      catch (SQLException ex)
+      {
+        throw new DBException("Could not extract CLOB value", ex);
+      }
+    }
+
+    return value;
+  }
+
+  private Map<String, Object> toMap(String[] columnNames, Object[] results)
+  {
+    Map<String, Object> ret = new HashMap<String, Object>();
+
+    for (int i = 0; i < columnNames.length; i++)
+    {
+      String columnName = columnNames[i];
+      ret.put(columnName, results[i]);
+    }
+
+    return ret;
+  }
+
+  private String parse(String query, Map<String, List<Integer>> paramMap)
+  {
+    int length = query.length();
+    StringBuilder builder = new StringBuilder(length);
+
+    boolean inSingleQuote = false;
+    boolean inDoubleQuote = false;
+    int index = 1;
+
+    for (int i = 0; i < length; i++)
+    {
+      char c = query.charAt(i);
+      if (inSingleQuote)
+      {
+        if (c == '\'')
+        {
+          inSingleQuote = false;
+        }
+      }
+      else if (inDoubleQuote)
+      {
+        if (c == '"')
+        {
+          inDoubleQuote = false;
+        }
+      }
+      else
+      {
+        if (c == '\'')
+        {
+          inSingleQuote = true;
+        }
+        else if (c == '"')
+        {
+          inDoubleQuote = true;
+        }
+        else if (c == ':' && i + 1 < length && Character.isJavaIdentifierStart(query.charAt(i + 1)))
+        {
+          int j = i + 2;
+          while (j < length && Character.isJavaIdentifierPart(query.charAt(j)))
+          {
+            j++;
+          }
+
+          String name = query.substring(i + 1, j);
+          c = '?';
+          i += name.length();
+
+          List<Integer> indexList = paramMap.get(name);
+          if (indexList == null)
+          {
+            indexList = new ArrayList<Integer>();
+            paramMap.put(name, indexList);
+          }
+
+          indexList.add(new Integer(index));
+          index++;
+        }
+      }
+
+      builder.append(c);
+    }
+
+    return builder.toString();
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/SmartPreparedStatementCache.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/SmartPreparedStatementCache.java
new file mode 100644
index 0000000..0ea0e91
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/SmartPreparedStatementCache.java
@@ -0,0 +1,291 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Stefan Winkler - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server.internal.db;
+
+import org.eclipse.emf.cdo.server.internal.db.bundle.OM;
+
+import org.eclipse.net4j.db.DBException;
+import org.eclipse.net4j.util.ImplementationError;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.HashMap;
+
+/**
+ * @author Stefan Winkler
+ * @since 2.0
+ */
+public class SmartPreparedStatementCache extends AbstractPreparedStatementCache
+{
+  private Cache cache;
+
+  private HashMap<PreparedStatement, CachedPreparedStatement> checkedOut = new HashMap<PreparedStatement, CachedPreparedStatement>();
+
+  public SmartPreparedStatementCache(int capacity)
+  {
+    cache = new Cache(capacity);
+  }
+
+  public PreparedStatement getPreparedStatement(String sql, ReuseProbability reuseProbability)
+  {
+    CachedPreparedStatement cachedStatement = cache.remove(sql);
+    if (cachedStatement == null)
+    {
+      cachedStatement = createCachedPreparedStatement(sql, reuseProbability);
+    }
+
+    PreparedStatement result = cachedStatement.getPreparedStatement();
+    checkedOut.put(result, cachedStatement);
+
+    return result;
+  }
+
+  /**
+   * @param ps
+   *          the prepared statement to be released to the cache, or <code>null</code>.
+   */
+  public void releasePreparedStatement(PreparedStatement ps)
+  {
+    if (ps != null) // Bug 276926: Silently accept ps == null and do nothing.
+    {
+      CachedPreparedStatement cachedStatement = checkedOut.remove(ps);
+      cache.put(cachedStatement);
+    }
+  }
+
+  @Override
+  protected void doBeforeDeactivate() throws Exception
+  {
+    if (!checkedOut.isEmpty())
+    {
+      OM.LOG.warn("Statement leak detected"); //$NON-NLS-1$
+    }
+  }
+
+  private CachedPreparedStatement createCachedPreparedStatement(String sql, ReuseProbability reuseProbability)
+  {
+    try
+    {
+      Connection connection = getConnection();
+      PreparedStatement stmt = connection.prepareStatement(sql);
+      return new CachedPreparedStatement(sql, reuseProbability, stmt);
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex);
+    }
+  }
+
+  /**
+   * @author Stefan Winkler
+   */
+  private static final class Cache
+  {
+    private CacheList lists[];
+
+    private HashMap<String, CachedPreparedStatement> lookup;
+
+    private int capacity;
+
+    public Cache(int capacity)
+    {
+      this.capacity = capacity;
+
+      lookup = new HashMap<String, CachedPreparedStatement>(capacity);
+
+      lists = new CacheList[ReuseProbability.values().length];
+      for (ReuseProbability prob : ReuseProbability.values())
+      {
+        lists[prob.ordinal()] = new CacheList();
+      }
+    }
+
+    public void put(CachedPreparedStatement cachedStatement)
+    {
+      // refresh age
+      cachedStatement.touch();
+
+      // put into appripriate list
+      lists[cachedStatement.getProbability().ordinal()].add(cachedStatement);
+
+      // put into lookup table
+      if (lookup.put(cachedStatement.getSQL(), cachedStatement) != null)
+      {
+        throw new ImplementationError(cachedStatement.getSQL() + " already in cache"); //$NON-NLS-1$
+      }
+
+      // handle capacity overflow
+      if (lookup.size() > capacity)
+      {
+        evictOne();
+      }
+    }
+
+    private void evictOne()
+    {
+      long maxAge = -1;
+      int ordinal = -1;
+
+      for (ReuseProbability prob : ReuseProbability.values())
+      {
+        if (!lists[prob.ordinal()].isEmpty())
+        {
+          long age = lists[prob.ordinal()].tail().getAge();
+          if (maxAge < age)
+          {
+            maxAge = age;
+            ordinal = prob.ordinal();
+          }
+        }
+      }
+
+      remove(lists[ordinal].tail().getSQL());
+    }
+
+    public CachedPreparedStatement remove(String sql)
+    {
+      CachedPreparedStatement result = lookup.remove(sql);
+      if (result == null)
+      {
+        return null;
+      }
+
+      lists[result.getProbability().ordinal()].remove(result);
+      return result;
+    }
+
+    /**
+     * @author Stefan Winkler
+     */
+    private class CacheList
+    {
+      private CachedPreparedStatement first;
+
+      private CachedPreparedStatement last;
+
+      public CacheList()
+      {
+      }
+
+      public void add(CachedPreparedStatement s)
+      {
+        if (first == null)
+        {
+          first = s;
+          last = s;
+          s.previous = null;
+          s.next = null;
+        }
+        else
+        {
+          first.previous = s;
+          s.next = first;
+          first = s;
+        }
+      }
+
+      public void remove(CachedPreparedStatement s)
+      {
+        if (s == first)
+        {
+          first = s.next;
+        }
+
+        if (s.next != null)
+        {
+          s.next.previous = s.previous;
+        }
+
+        if (s == last)
+        {
+          last = s.previous;
+        }
+
+        if (s.previous != null)
+        {
+          s.previous.next = s.next;
+        }
+
+        s.previous = null;
+        s.next = null;
+      }
+
+      public CachedPreparedStatement tail()
+      {
+        return last;
+      }
+
+      public boolean isEmpty()
+      {
+        return first == null;
+      }
+    }
+  }
+
+  /**
+   * @author Stefan Winkler
+   */
+  private static final class CachedPreparedStatement
+  {
+    private long timeStamp;
+
+    private String sql;
+
+    private ReuseProbability probability;
+
+    private PreparedStatement statement;
+
+    /**
+     * DL field
+     */
+    private CachedPreparedStatement previous;
+
+    /**
+     * DL field
+     */
+    private CachedPreparedStatement next;
+
+    public CachedPreparedStatement(String sql, ReuseProbability prob, PreparedStatement stmt)
+    {
+      this.sql = sql;
+      probability = prob;
+      statement = stmt;
+      timeStamp = System.currentTimeMillis();
+    }
+
+    public PreparedStatement getPreparedStatement()
+    {
+      return statement;
+    }
+
+    public long getAge()
+    {
+      long currentTime = System.currentTimeMillis();
+      return (currentTime - timeStamp) * probability.ordinal();
+    }
+
+    public void touch()
+    {
+      timeStamp = System.currentTimeMillis();
+    }
+
+    public String getSQL()
+    {
+      return sql;
+    }
+
+    public ReuseProbability getProbability()
+    {
+      return probability;
+    }
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/StringIDHandler.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/StringIDHandler.java
new file mode 100644
index 0000000..8039584
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/StringIDHandler.java
@@ -0,0 +1,249 @@
+/**

+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    Eike Stepper - initial API and implementation

+ */

+package org.eclipse.emf.cdo.server.internal.db;

+

+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;

+import org.eclipse.emf.cdo.common.id.CDOID;

+import org.eclipse.emf.cdo.common.id.CDOID.ObjectType;

+import org.eclipse.emf.cdo.common.id.CDOIDUtil;

+import org.eclipse.emf.cdo.common.protocol.CDODataInput;

+import org.eclipse.emf.cdo.common.protocol.CDODataOutput;

+import org.eclipse.emf.cdo.common.revision.CDORevision;

+import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;

+import org.eclipse.emf.cdo.server.db.IIDHandler;

+import org.eclipse.emf.cdo.server.db.mapping.ITypeMapping;

+import org.eclipse.emf.cdo.server.internal.db.mapping.CoreTypeMappings;

+

+import org.eclipse.net4j.db.DBType;

+import org.eclipse.net4j.util.lifecycle.Lifecycle;

+import org.eclipse.net4j.util.om.monitor.OMMonitor;

+

+import java.io.IOException;

+import java.sql.Connection;

+import java.sql.PreparedStatement;

+import java.sql.ResultSet;

+import java.sql.SQLException;

+import java.util.Collections;

+import java.util.Set;

+

+/**

+ * @author Eike Stepper

+ */

+public class StringIDHandler extends Lifecycle implements IIDHandler

+{

+  public static final Set<ObjectType> OBJECT_ID_TYPES = Collections.singleton(CDOID.ObjectType.STRING);

+

+  public static final CDOID MIN = CDOID.NULL;

+

+  public static final CDOID MAX = create(Long.toString(Long.MAX_VALUE));

+

+  private DBStore store;

+

+  private long lastObjectID = 0;

+

+  private long nextLocalObjectID = Long.MAX_VALUE;

+

+  public StringIDHandler(DBStore store)

+  {

+    this.store = store;

+  }

+

+  public DBStore getStore()

+  {

+    return store;

+  }

+

+  public int compare(CDOID id1, CDOID id2)

+  {

+    if (id1.getType() == CDOID.Type.OBJECT && id2.getType() == CDOID.Type.OBJECT)

+    {

+      return Long.valueOf(value(id1)).compareTo(Long.valueOf(value(id2)));

+    }

+

+    return id1.compareTo(id2);

+  }

+

+  public DBType getDBType()

+  {

+    return DBType.VARCHAR;

+  }

+

+  public Set<ObjectType> getObjectIDTypes()

+  {

+    return OBJECT_ID_TYPES;

+  }

+

+  public CDOID createCDOID(String val)

+  {

+    return create(val);

+  }

+

+  public synchronized CDOID getLastObjectID()

+  {

+    return CDOIDUtil.createString("" + lastObjectID);

+  }

+

+  public synchronized void setLastObjectID(CDOID lastObjectID)

+  {

+    this.lastObjectID = Long.parseLong(value(lastObjectID));

+  }

+

+  public void adjustLastObjectID(CDOID maxID)

+  {

+    // TODO: implement StringIDHandler.adjustLastObjectID(maxID)

+    throw new UnsupportedOperationException();

+  }

+

+  public synchronized CDOID getNextLocalObjectID()

+  {

+    return CDOIDUtil.createString("" + nextLocalObjectID);

+  }

+

+  public synchronized void setNextLocalObjectID(CDOID nextLocalObjectID)

+  {

+    this.nextLocalObjectID = Long.parseLong(value(nextLocalObjectID));

+  }

+

+  public synchronized CDOID getNextCDOID(CDORevision revision)

+  {

+    if (revision.getBranch().isLocal())

+    {

+      return CDOIDUtil.createString("" + nextLocalObjectID--);

+    }

+

+    return CDOIDUtil.createString("" + ++lastObjectID);

+  }

+

+  public boolean isLocalCDOID(CDOID id)

+  {

+    if (id.getType() == CDOID.Type.OBJECT)

+    {

+      return Long.parseLong(value(id)) > nextLocalObjectID;

+    }

+

+    return false;

+  }

+

+  public ITypeMapping getObjectTypeMapping()

+  {

+    return new CoreTypeMappings.TMObject();

+  }

+

+  public void appendCDOID(StringBuilder builder, CDOID id)

+  {

+    builder.append("'");

+    builder.append(value(id));

+    builder.append("'");

+  }

+

+  public void setCDOID(PreparedStatement stmt, int column, CDOID id) throws SQLException

+  {

+    setCDOID(stmt, column, id, CDOBranchPoint.INVALID_DATE);

+  }

+

+  public void setCDOID(PreparedStatement stmt, int column, CDOID id, long commitTime) throws SQLException

+  {

+    String value = value(id);

+    stmt.setString(column, value == null || value.length() == 0 ? "0" : value);

+  }

+

+  public CDOID getCDOID(ResultSet resultSet, int column) throws SQLException

+  {

+    String id = resultSet.getString(column);

+    if (resultSet.wasNull())

+    {

+      return null;

+    }

+

+    return create(id);

+  }

+

+  public CDOID getCDOID(ResultSet resultSet, String name) throws SQLException

+  {

+    String id = resultSet.getString(name);

+    if (resultSet.wasNull())

+    {

+      return null;

+    }

+

+    return create(id);

+  }

+

+  public CDOID getMinCDOID()

+  {

+    return MIN;

+  }

+

+  public CDOID getMaxCDOID()

+  {

+    return MAX;

+  }

+

+  public CDOID mapURI(IDBStoreAccessor accessor, String uri, long commitTime)

+  {

+    return create(uri);

+  }

+

+  public String unmapURI(IDBStoreAccessor accessor, CDOID id)

+  {

+    return value(id);

+  }

+

+  public void rawExport(Connection connection, CDODataOutput out, long fromCommitTime, long toCommitTime)

+      throws IOException

+  {

+    // Do nothing

+  }

+

+  public void rawImport(Connection connection, CDODataInput in, long fromCommitTime, long toCommitTime,

+      OMMonitor monitor) throws IOException

+  {

+    // Do nothing

+  }

+

+  private static CDOID create(String id)

+  {

+    if (id == null)

+    {

+      return null;

+    }

+

+    int length = id.length();

+    if (length == 0)

+    {

+      return null;

+    }

+

+    char firstChar = id.charAt(0);

+    if (length == 1 && firstChar == '0')

+    {

+      return null;

+    }

+

+    if (Character.isDigit(firstChar))

+    {

+      long value = Long.parseLong(id);

+      if (value < 0)

+      {

+        throw new IllegalArgumentException("Illegal ID value: " + id);

+      }

+

+      return CDOIDUtil.createString(id);

+    }

+

+    return CDOIDUtil.createExternal(id);

+  }

+

+  private static String value(CDOID id)

+  {

+    return CDOIDUtil.getString(id);

+  }

+}

diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/UUIDHandler.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/UUIDHandler.java
new file mode 100644
index 0000000..088cf83
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/UUIDHandler.java
@@ -0,0 +1,237 @@
+/**

+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    Eike Stepper - initial API and implementation

+ */

+package org.eclipse.emf.cdo.server.internal.db;

+

+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;

+import org.eclipse.emf.cdo.common.id.CDOID;

+import org.eclipse.emf.cdo.common.id.CDOID.ObjectType;

+import org.eclipse.emf.cdo.common.id.CDOIDUtil;

+import org.eclipse.emf.cdo.common.protocol.CDODataInput;

+import org.eclipse.emf.cdo.common.protocol.CDODataOutput;

+import org.eclipse.emf.cdo.common.revision.CDORevision;

+import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;

+import org.eclipse.emf.cdo.server.db.IIDHandler;

+import org.eclipse.emf.cdo.server.db.mapping.ITypeMapping;

+import org.eclipse.emf.cdo.server.internal.db.mapping.CoreTypeMappings;

+

+import org.eclipse.net4j.db.DBType;

+import org.eclipse.net4j.util.lifecycle.Lifecycle;

+import org.eclipse.net4j.util.om.monitor.OMMonitor;

+

+import java.io.IOException;

+import java.sql.Connection;

+import java.sql.PreparedStatement;

+import java.sql.ResultSet;

+import java.sql.SQLException;

+import java.util.Collections;

+import java.util.Set;

+

+/**

+ * @author Eike Stepper

+ */

+public class UUIDHandler extends Lifecycle implements IIDHandler

+{

+  public static final Set<ObjectType> OBJECT_ID_TYPES = Collections.singleton(ObjectType.UUID);

+

+  private static final char NULL_CHAR = '0';

+

+  private static final String NULL_STRING = Character.toString(NULL_CHAR);

+

+  private static final char INTERNAL_CHAR = '@';

+

+  private static final String INTERNAL_STRING = Character.toString(INTERNAL_CHAR);

+

+  private DBStore store;

+

+  public UUIDHandler(DBStore store)

+  {

+    this.store = store;

+  }

+

+  public DBStore getStore()

+  {

+    return store;

+  }

+

+  public int compare(CDOID id1, CDOID id2)

+  {

+    throw new UnsupportedOperationException();

+  }

+

+  public DBType getDBType()

+  {

+    return DBType.VARCHAR;

+  }

+

+  public Set<ObjectType> getObjectIDTypes()

+  {

+    return OBJECT_ID_TYPES;

+  }

+

+  public CDOID createCDOID(String val)

+  {

+    return create(INTERNAL_STRING + val);

+  }

+

+  public synchronized CDOID getLastObjectID()

+  {

+    throw new UnsupportedOperationException();

+  }

+

+  public synchronized void setLastObjectID(CDOID lastObjectID)

+  {

+    // Do nothing

+  }

+

+  public void adjustLastObjectID(CDOID maxID)

+  {

+    // Do nothing

+  }

+

+  public synchronized CDOID getNextLocalObjectID()

+  {

+    throw new UnsupportedOperationException();

+  }

+

+  public synchronized void setNextLocalObjectID(CDOID nextLocalObjectID)

+  {

+    // Do nothing

+  }

+

+  public synchronized CDOID getNextCDOID(CDORevision revision)

+  {

+    throw new UnsupportedOperationException();

+  }

+

+  public boolean isLocalCDOID(CDOID id)

+  {

+    return false;

+  }

+

+  public ITypeMapping getObjectTypeMapping()

+  {

+    return new CoreTypeMappings.TMObject();

+  }

+

+  public void appendCDOID(StringBuilder builder, CDOID id)

+  {

+    builder.append("'");

+    builder.append(value(id));

+    builder.append("'");

+  }

+

+  public void setCDOID(PreparedStatement stmt, int column, CDOID id) throws SQLException

+  {

+    setCDOID(stmt, column, id, CDOBranchPoint.INVALID_DATE);

+  }

+

+  public void setCDOID(PreparedStatement stmt, int column, CDOID id, long commitTime) throws SQLException

+  {

+    stmt.setString(column, value(id));

+  }

+

+  public CDOID getCDOID(ResultSet resultSet, int column) throws SQLException

+  {

+    String id = resultSet.getString(column);

+    if (resultSet.wasNull())

+    {

+      return null;

+    }

+

+    return create(id);

+  }

+

+  public CDOID getCDOID(ResultSet resultSet, String name) throws SQLException

+  {

+    String id = resultSet.getString(name);

+    if (resultSet.wasNull())

+    {

+      return null;

+    }

+

+    return create(id);

+  }

+

+  public CDOID getMinCDOID()

+  {

+    throw new UnsupportedOperationException();

+  }

+

+  public CDOID getMaxCDOID()

+  {

+    throw new UnsupportedOperationException();

+  }

+

+  public CDOID mapURI(IDBStoreAccessor accessor, String uri, long commitTime)

+  {

+    return CDOIDUtil.createExternal(uri);

+  }

+

+  public String unmapURI(IDBStoreAccessor accessor, CDOID id)

+  {

+    return CDOIDUtil.getString(id);

+  }

+

+  public void rawExport(Connection connection, CDODataOutput out, long fromCommitTime, long toCommitTime)

+      throws IOException

+  {

+    // Do nothing

+  }

+

+  public void rawImport(Connection connection, CDODataInput in, long fromCommitTime, long toCommitTime,

+      OMMonitor monitor) throws IOException

+  {

+    // Do nothing

+  }

+

+  private static CDOID create(String id)

+  {

+    if (id == null)

+    {

+      return null;

+    }

+

+    int length = id.length();

+    if (length == 0)

+    {

+      return null;

+    }

+

+    char firstChar = id.charAt(0);

+    if (length == 1 && firstChar == NULL_CHAR)

+    {

+      return null;

+    }

+

+    if (firstChar == INTERNAL_CHAR)

+    {

+      byte[] bytes = CDOIDUtil.decodeUUID(id.substring(1));

+      return CDOIDUtil.createUUID(bytes);

+    }

+

+    return CDOIDUtil.createExternal(id);

+  }

+

+  private static String value(CDOID id)

+  {

+    if (CDOIDUtil.isNull(id))

+    {

+      return NULL_STRING;

+    }

+

+    if (id.isExternal())

+    {

+      return CDOIDUtil.getString(id);

+    }

+

+    return INTERNAL_STRING + id.toURIFragment();

+  }

+}

diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/bundle/OM.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/bundle/OM.java
new file mode 100644
index 0000000..d45d95c
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/bundle/OM.java
@@ -0,0 +1,45 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - Bug 285426: [DB] Implement user-defined typeMapping support
+ */
+package org.eclipse.emf.cdo.server.internal.db.bundle;
+
+import org.eclipse.net4j.util.om.OMBundle;
+import org.eclipse.net4j.util.om.OMPlatform;
+import org.eclipse.net4j.util.om.OSGiActivator;
+import org.eclipse.net4j.util.om.log.OMLogger;
+import org.eclipse.net4j.util.om.trace.OMTracer;
+
+/**
+ * The <em>Operations & Maintenance</em> class of this bundle.
+ * 
+ * @author Eike Stepper
+ */
+public abstract class OM
+{
+  public static final String BUNDLE_ID = "org.eclipse.emf.cdo.server.db"; //$NON-NLS-1$
+
+  public static final OMBundle BUNDLE = OMPlatform.INSTANCE.bundle(BUNDLE_ID, OM.class);
+
+  public static final OMTracer DEBUG = BUNDLE.tracer("debug"); //$NON-NLS-1$
+
+  public static final OMLogger LOG = BUNDLE.logger();
+
+  /**
+   * @author Eike Stepper
+   */
+  public static final class Activator extends OSGiActivator
+  {
+    public Activator()
+    {
+      super(BUNDLE);
+    }
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/jdbc/WrappedPreparedStatement.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/jdbc/WrappedPreparedStatement.java
new file mode 100644
index 0000000..d4781d3
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/jdbc/WrappedPreparedStatement.java
@@ -0,0 +1,81 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server.internal.db.jdbc;
+
+import org.eclipse.emf.cdo.server.internal.db.bundle.OM;
+
+import org.eclipse.net4j.db.DBUtil;
+import org.eclipse.net4j.util.om.trace.ContextTracer;
+
+import java.sql.PreparedStatement;
+import java.text.MessageFormat;
+
+/**
+ * Wrapper for a prepared statement that is cleaned up when it is cached in a WeakReferenceCache and gc'd. Note that
+ * this is just a wrapper with access to its wrapped object. There's no interface delegation, because the interface
+ * delegation would also put the necessity to wrap resultSets and maybe even more, which seems to much overkill for a
+ * simple internal implementation.
+ * 
+ * @author Stefan Winkler
+ */
+public class WrappedPreparedStatement
+{
+  private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG, WrappedPreparedStatement.class);
+
+  private PreparedStatement wrappedStatement;
+
+  public WrappedPreparedStatement(PreparedStatement ps)
+  {
+    wrappedStatement = ps;
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Wrapping Statement: {0}", wrappedStatement); //$NON-NLS-1$
+    }
+  }
+
+  public PreparedStatement getWrappedStatement()
+  {
+    return wrappedStatement;
+  }
+
+  public PreparedStatement unwrapStatement()
+  {
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("UnWrapping Statement: {0}", wrappedStatement); //$NON-NLS-1$
+    }
+
+    PreparedStatement result = wrappedStatement;
+    wrappedStatement = null;
+    return result;
+  }
+
+  @Override
+  public String toString()
+  {
+    return MessageFormat.format("Wrapped[{0}]", wrappedStatement); //$NON-NLS-1$
+  }
+
+  @Override
+  protected void finalize() throws Throwable
+  {
+    if (wrappedStatement != null)
+    {
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Closing statement: {0}", wrappedStatement); //$NON-NLS-1$
+      }
+
+      DBUtil.close(wrappedStatement);
+      wrappedStatement = null;
+    }
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/AbstractMappingStrategy.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/AbstractMappingStrategy.java
new file mode 100644
index 0000000..d9c76b3
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/AbstractMappingStrategy.java
@@ -0,0 +1,641 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - major refactoring
+ *    Stefan Winkler - Bug 271444: [DB] Multiple refactorings bug 271444
+ *    Stefan Winkler - Bug 282976: [DB] Influence Mappings through EAnnotations
+ *    Kai Schlamp - Bug 284680 - [DB] Provide annotation to bypass ClassMapping
+ *    Stefan Winkler - maintenance
+ *    Stefan Winkler - Bug 285426: [DB] Implement user-defined typeMapping support
+ */
+package org.eclipse.emf.cdo.server.internal.db.mapping;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.id.CDOIDUtil;
+import org.eclipse.emf.cdo.common.model.CDOModelUtil;
+import org.eclipse.emf.cdo.common.model.EMFUtil;
+import org.eclipse.emf.cdo.common.revision.CDORevisionHandler;
+import org.eclipse.emf.cdo.server.IStoreAccessor.CommitContext;
+import org.eclipse.emf.cdo.server.StoreThreadLocal;
+import org.eclipse.emf.cdo.server.db.IDBStore;
+import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
+import org.eclipse.emf.cdo.server.db.IMetaDataManager;
+import org.eclipse.emf.cdo.server.db.IPreparedStatementCache;
+import org.eclipse.emf.cdo.server.db.mapping.IClassMapping;
+import org.eclipse.emf.cdo.server.db.mapping.IListMapping;
+import org.eclipse.emf.cdo.server.db.mapping.IMappingStrategy;
+import org.eclipse.emf.cdo.server.db.mapping.ITypeMapping;
+import org.eclipse.emf.cdo.server.internal.db.DBAnnotation;
+import org.eclipse.emf.cdo.server.internal.db.ObjectIDIterator;
+import org.eclipse.emf.cdo.spi.common.commit.CDOChangeSetSegment;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageInfo;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit;
+import org.eclipse.emf.cdo.spi.server.InternalRepository;
+
+import org.eclipse.net4j.db.DBException;
+import org.eclipse.net4j.db.DBUtil;
+import org.eclipse.net4j.db.ddl.IDBSchema;
+import org.eclipse.net4j.db.ddl.IDBTable;
+import org.eclipse.net4j.util.ImplementationError;
+import org.eclipse.net4j.util.StringUtil;
+import org.eclipse.net4j.util.collection.CloseableIterator;
+import org.eclipse.net4j.util.lifecycle.Lifecycle;
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+import org.eclipse.net4j.util.om.monitor.OMMonitor.Async;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EClassifier;
+import org.eclipse.emf.ecore.ENamedElement;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.util.FeatureMapUtil;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * This abstract base class implements those methods which are most likely common to most mapping strategies. It can be
+ * used to derive custom mapping strategy implementation.
+ * 
+ * @author Eike Stepper
+ * @since 2.0
+ */
+public abstract class AbstractMappingStrategy extends Lifecycle implements IMappingStrategy
+{
+  // --------- database name generation strings --------------
+  protected static final String NAME_SEPARATOR = "_"; //$NON-NLS-1$
+
+  protected static final String TYPE_PREFIX_FEATURE = "F"; //$NON-NLS-1$
+
+  protected static final String TYPE_PREFIX_CLASS = "C"; //$NON-NLS-1$
+
+  protected static final String TYPE_PREFIX_PACKAGE = "P"; //$NON-NLS-1$
+
+  protected static final String GENERAL_PREFIX = "X"; //$NON-NLS-1$
+
+  protected static final String GENERAL_SUFFIX = "0"; //$NON-NLS-1$
+
+  /**
+   * Prefix for unsettable feature helper columns
+   */
+  protected static final String CDO_SET_PREFIX = "cdo_set_"; //$NON-NLS-1$
+
+  protected static final String FEATURE_TABLE_SUFFIX = "_list"; //$NON-NLS-1$
+
+  private IDBStore store;
+
+  private Map<String, String> properties;
+
+  private ConcurrentMap<EClass, IClassMapping> classMappings;
+
+  private boolean allClassMappingsCreated;
+
+  public AbstractMappingStrategy()
+  {
+    classMappings = new ConcurrentHashMap<EClass, IClassMapping>();
+  }
+
+  // -- property related methods -----------------------------------------
+
+  public synchronized Map<String, String> getProperties()
+  {
+    if (properties == null)
+    {
+      properties = new HashMap<String, String>();
+    }
+
+    return properties;
+  }
+
+  public synchronized void setProperties(Map<String, String> properties)
+  {
+    this.properties = properties;
+  }
+
+  private int getMaxTableNameLength()
+  {
+    String value = getProperties().get(PROP_MAX_TABLE_NAME_LENGTH);
+    return value == null ? store.getDBAdapter().getMaxTableNameLength() : Integer.valueOf(value);
+  }
+
+  private int getMaxFieldNameLength()
+  {
+    String value = getProperties().get(PROP_MAX_FIELD_NAME_LENGTH);
+    return value == null ? store.getDBAdapter().getMaxFieldNameLength() : Integer.valueOf(value);
+  }
+
+  private boolean isQualifiedNames()
+  {
+    String value = getProperties().get(PROP_QUALIFIED_NAMES);
+    return value == null ? false : Boolean.valueOf(value);
+  }
+
+  private boolean isForceNamesWithID()
+  {
+    String value = getProperties().get(PROP_FORCE_NAMES_WITH_ID);
+    return value == null ? false : Boolean.valueOf(value);
+  }
+
+  private String getTableNamePrefix()
+  {
+    String value = getProperties().get(PROP_TABLE_NAME_PREFIX);
+    return StringUtil.safe(value);
+  }
+
+  // -- getters and setters ----------------------------------------------
+
+  public final IDBStore getStore()
+  {
+    return store;
+  }
+
+  public final void setStore(IDBStore dbStore)
+  {
+    checkInactive();
+    store = dbStore;
+  }
+
+  protected final IMetaDataManager getMetaDataManager()
+  {
+    return getStore().getMetaDataManager();
+  }
+
+  // -- object id related methods ----------------------------------------
+
+  public void handleRevisions(IDBStoreAccessor accessor, EClass eClass, CDOBranch branch, long timeStamp,
+      boolean exactTime, CDORevisionHandler handler)
+  {
+    if (eClass == null)
+    {
+      Collection<IClassMapping> values = getClassMappings().values();
+      for (IClassMapping mapping : values)
+      {
+        mapping.handleRevisions(accessor, branch, timeStamp, exactTime, handler);
+      }
+    }
+    else
+    {
+      IClassMapping classMapping = getClassMapping(eClass);
+      classMapping.handleRevisions(accessor, branch, timeStamp, exactTime, handler);
+    }
+  }
+
+  public Set<CDOID> readChangeSet(IDBStoreAccessor accessor, OMMonitor monitor, CDOChangeSetSegment[] segments)
+  {
+    Set<CDOID> result = new HashSet<CDOID>();
+    Collection<IClassMapping> classMappings = getClassMappings().values();
+
+    monitor.begin(classMappings.size());
+
+    try
+    {
+      for (IClassMapping mapping : classMappings)
+      {
+        Async async = monitor.forkAsync();
+
+        try
+        {
+          Set<CDOID> ids = mapping.readChangeSet(accessor, segments);
+          result.addAll(ids);
+        }
+        finally
+        {
+          async.stop();
+        }
+      }
+
+      return result;
+    }
+    finally
+    {
+      monitor.done();
+    }
+  }
+
+  public CloseableIterator<CDOID> readObjectIDs(IDBStoreAccessor accessor)
+  {
+    Collection<EClass> classes = getClassesWithObjectInfo();
+    final Iterator<EClass> classIt = classes.iterator();
+
+    return new ObjectIDIterator(this, accessor)
+    {
+      private PreparedStatement currentStatement;
+
+      @Override
+      protected ResultSet getNextResultSet()
+      {
+        while (classIt.hasNext())
+        {
+          EClass eClass = classIt.next();
+          IClassMapping mapping = getClassMapping(eClass);
+          currentStatement = mapping.createObjectIDStatement(getAccessor());
+
+          ResultSet resultSet = null;
+
+          try
+          {
+            resultSet = currentStatement.executeQuery();
+            return resultSet;
+          }
+          catch (Exception ex)
+          {
+            DBUtil.close(resultSet); // only on error
+            releaseCurrentStatement();
+            throw new DBException(ex);
+          }
+        }
+
+        return null;
+      }
+
+      @Override
+      protected void closeCurrentResultSet()
+      {
+        super.closeCurrentResultSet();
+        releaseCurrentStatement();
+      }
+
+      private void releaseCurrentStatement()
+      {
+        IPreparedStatementCache statementCache = getAccessor().getStatementCache();
+        statementCache.releasePreparedStatement(currentStatement);
+        currentStatement = null;
+      }
+    };
+  }
+
+  protected abstract Collection<EClass> getClassesWithObjectInfo();
+
+  // -- database name demangling methods ---------------------------------
+
+  public String getTableName(ENamedElement element)
+  {
+    String name = null;
+    String typePrefix = null;
+
+    if (element instanceof EClass)
+    {
+      typePrefix = TYPE_PREFIX_CLASS;
+      name = DBAnnotation.TABLE_NAME.getValue(element);
+      if (name == null)
+      {
+        name = isQualifiedNames() ? EMFUtil.getQualifiedName((EClass)element, NAME_SEPARATOR) : element.getName();
+      }
+    }
+    else if (element instanceof EPackage)
+    {
+      typePrefix = TYPE_PREFIX_PACKAGE;
+      name = DBAnnotation.TABLE_NAME.getValue(element);
+      if (name == null)
+      {
+        name = isQualifiedNames() ? EMFUtil.getQualifiedName((EPackage)element, NAME_SEPARATOR) : element.getName();
+      }
+    }
+    else
+    {
+      throw new ImplementationError("Unknown element: " + element); //$NON-NLS-1$
+    }
+
+    String prefix = getTableNamePrefix();
+    if (prefix.length() != 0 && !prefix.endsWith(NAME_SEPARATOR))
+    {
+      prefix += NAME_SEPARATOR;
+    }
+
+    return getName(prefix + name, typePrefix + getUniqueID(element), getMaxTableNameLength());
+  }
+
+  public String getTableName(EClass eClass, EStructuralFeature feature)
+  {
+    String name = DBAnnotation.TABLE_NAME.getValue(eClass);
+    if (name == null)
+    {
+      name = isQualifiedNames() ? EMFUtil.getQualifiedName(eClass, NAME_SEPARATOR) : eClass.getName();
+    }
+
+    name += NAME_SEPARATOR;
+    name += feature.getName();
+    name += FEATURE_TABLE_SUFFIX;
+
+    String prefix = getTableNamePrefix();
+    if (prefix.length() != 0 && !prefix.endsWith(NAME_SEPARATOR))
+    {
+      prefix += NAME_SEPARATOR;
+    }
+
+    return getName(prefix + name, TYPE_PREFIX_FEATURE + getUniqueID(feature), getMaxTableNameLength());
+  }
+
+  public String getFieldName(EStructuralFeature feature)
+  {
+    String name = DBAnnotation.COLUMN_NAME.getValue(feature);
+    if (name == null)
+    {
+      name = getName(feature.getName(), TYPE_PREFIX_FEATURE + getUniqueID(feature), getMaxFieldNameLength());
+    }
+
+    return name;
+  }
+
+  public String getUnsettableFieldName(EStructuralFeature feature)
+  {
+    String name = DBAnnotation.COLUMN_NAME.getValue(feature);
+    if (name != null)
+    {
+      return CDO_SET_PREFIX + name;
+    }
+
+    return getName(CDO_SET_PREFIX + feature.getName(), TYPE_PREFIX_FEATURE + getUniqueID(feature),
+        getMaxFieldNameLength());
+  }
+
+  private String getName(String name, String suffix, int maxLength)
+  {
+    if (!store.getDBAdapter().isValidFirstChar(name.charAt(0)))
+    {
+      name = GENERAL_PREFIX + name;
+    }
+
+    boolean forceNamesWithID = isForceNamesWithID();
+    if (!forceNamesWithID && store.getDBAdapter().isReservedWord(name))
+    {
+      name = name + GENERAL_SUFFIX;
+    }
+
+    if (name.length() > maxLength || forceNamesWithID)
+    {
+      suffix = NAME_SEPARATOR + suffix.replace('-', 'S');
+      int length = Math.min(name.length(), maxLength - suffix.length());
+      name = name.substring(0, length) + suffix;
+    }
+
+    return name;
+  }
+
+  private String getUniqueID(ENamedElement element)
+  {
+    long timeStamp;
+    CommitContext commitContext = StoreThreadLocal.getCommitContext();
+    if (commitContext != null)
+    {
+      timeStamp = commitContext.getBranchPoint().getTimeStamp();
+    }
+    else
+    {
+      // This happens outside a commit, i.e. at system init time.
+      // Ensure that resulting ext refs are not replicated!
+      timeStamp = CDOBranchPoint.INVALID_DATE;
+
+      // timeStamp = getStore().getRepository().getTimeStamp();
+    }
+
+    CDOID result = getMetaDataManager().getMetaID(element, timeStamp);
+
+    StringBuilder builder = new StringBuilder();
+    CDOIDUtil.write(builder, result);
+    return builder.toString();
+  }
+
+  // -- factories for mapping of classes, values, lists ------------------
+
+  public void createMapping(Connection connection, InternalCDOPackageUnit[] packageUnits, OMMonitor monitor)
+  {
+    Async async = null;
+    monitor.begin();
+
+    try
+    {
+      async = monitor.forkAsync();
+
+      try
+      {
+        mapPackageUnits(packageUnits, connection, false);
+      }
+      finally
+      {
+        if (async != null)
+        {
+          async.stop();
+        }
+      }
+    }
+    finally
+    {
+      monitor.done();
+    }
+  }
+
+  public void removeMapping(Connection connection, InternalCDOPackageUnit[] packageUnits)
+  {
+    mapPackageUnits(packageUnits, connection, true);
+  }
+
+  private void mapPackageUnits(InternalCDOPackageUnit[] packageUnits, Connection connection, boolean unmap)
+  {
+    if (packageUnits != null && packageUnits.length != 0)
+    {
+      for (InternalCDOPackageUnit packageUnit : packageUnits)
+      {
+        mapPackageInfos(packageUnit.getPackageInfos(), connection, unmap);
+      }
+    }
+  }
+
+  private void mapPackageInfos(InternalCDOPackageInfo[] packageInfos, Connection connection, boolean unmap)
+  {
+    boolean supportingEcore = getStore().getRepository().isSupportingEcore();
+    for (InternalCDOPackageInfo packageInfo : packageInfos)
+    {
+      EPackage ePackage = packageInfo.getEPackage();
+      if (!CDOModelUtil.isCorePackage(ePackage) || supportingEcore)
+      {
+        mapClasses(connection, unmap, EMFUtil.getPersistentClasses(ePackage));
+      }
+    }
+  }
+
+  private void mapClasses(Connection connection, boolean unmap, EClass... eClasses)
+  {
+    for (EClass eClass : eClasses)
+    {
+      if (!(eClass.isInterface() || eClass.isAbstract()))
+      {
+        String mappingAnnotation = DBAnnotation.TABLE_MAPPING.getValue(eClass);
+
+        // TODO Maybe we should explicitly report unknown values of the annotation
+        if (mappingAnnotation != null && mappingAnnotation.equalsIgnoreCase(DBAnnotation.TABLE_MAPPING_NONE))
+        {
+          continue;
+        }
+
+        if (!unmap)
+        {
+          // TODO Bugzilla 296087: Before we go ahead with creation, we should check if it's already there
+          IClassMapping mapping = createClassMapping(eClass);
+          getStore().getDBAdapter().createTables(mapping.getDBTables(), connection);
+        }
+        else
+        {
+          IClassMapping mapping = removeClassMapping(eClass);
+          getStore().getDBAdapter().dropTables(mapping.getDBTables(), connection);
+        }
+      }
+    }
+  }
+
+  private IClassMapping createClassMapping(EClass eClass)
+  {
+    IClassMapping mapping = doCreateClassMapping(eClass);
+    if (mapping != null)
+    {
+      classMappings.put(eClass, mapping);
+    }
+
+    return mapping;
+  }
+
+  private IClassMapping removeClassMapping(EClass eClass)
+  {
+    IClassMapping mapping = classMappings.get(eClass);
+    if (mapping != null)
+    {
+      IDBSchema schema = getStore().getDBSchema();
+      for (IDBTable table : mapping.getDBTables())
+      {
+        schema.removeTable(table.getName());
+      }
+      classMappings.remove(eClass);
+    }
+    return mapping;
+  }
+
+  protected abstract IClassMapping doCreateClassMapping(EClass eClass);
+
+  public final IClassMapping getClassMapping(EClass eClass)
+  {
+    if (!isMapped(eClass))
+    {
+      throw new IllegalArgumentException("Class is not mapped: " + eClass);
+    }
+
+    // Try without synchronization first; this will almost always succeed, so it avoids the
+    // performance penalty of syncing in the majority of cases
+    IClassMapping result = classMappings.get(eClass);
+    if (result == null)
+    {
+      // Synchronize on the classMappings to prevent concurrent invocations of createClassMapping
+      // (Synchronizing on the eClass allows for more concurrency, but is risky because application
+      // code may be syncing on the eClass also.)
+      synchronized (classMappings)
+      {
+        // Check again, because other thread may have just added the mapping
+        result = classMappings.get(eClass);
+        if (result == null)
+        {
+          result = createClassMapping(eClass);
+        }
+      }
+    }
+
+    return result;
+  }
+
+  public final Map<EClass, IClassMapping> getClassMappings()
+  {
+    return getClassMappings(true);
+  }
+
+  public final Map<EClass, IClassMapping> getClassMappings(boolean createOnDemand)
+  {
+    return doGetClassMappings(createOnDemand);
+  }
+
+  public final Map<EClass, IClassMapping> doGetClassMappings(boolean createOnDemand)
+  {
+    if (createOnDemand)
+    {
+      synchronized (classMappings)
+      {
+        if (!allClassMappingsCreated)
+        {
+          createAllClassMappings();
+          allClassMappingsCreated = true;
+        }
+      }
+    }
+
+    return classMappings;
+  }
+
+  private void createAllClassMappings()
+  {
+    InternalRepository repository = (InternalRepository)getStore().getRepository();
+    InternalCDOPackageRegistry packageRegistry = repository.getPackageRegistry(false);
+    for (InternalCDOPackageInfo packageInfo : packageRegistry.getPackageInfos())
+    {
+      if (!packageInfo.isSystemPackage())
+      {
+        for (EClassifier eClassifier : packageInfo.getEPackage().getEClassifiers())
+        {
+          if (eClassifier instanceof EClass)
+          {
+            EClass eClass = (EClass)eClassifier;
+            if (isMapped(eClass))
+            {
+              getClassMapping(eClass); // Get or create it
+            }
+          }
+        }
+      }
+    }
+  }
+
+  protected abstract boolean isMapped(EClass eClass);
+
+  public ITypeMapping createValueMapping(EStructuralFeature feature)
+  {
+    ITypeMapping.Provider provider = getTypeMappingProvider();
+    return provider.createTypeMapping(this, feature);
+  }
+
+  protected ITypeMapping.Provider getTypeMappingProvider()
+  {
+    return ITypeMapping.Provider.INSTANCE;
+  }
+
+  public final IListMapping createListMapping(EClass containingClass, EStructuralFeature feature)
+  {
+    checkArg(feature.isMany(), "Only many-valued features allowed"); //$NON-NLS-1$
+    IListMapping mapping = doCreateListMapping(containingClass, feature);
+    return mapping;
+  }
+
+  public final IListMapping createFeatureMapMapping(EClass containingClass, EStructuralFeature feature)
+  {
+    checkArg(FeatureMapUtil.isFeatureMap(feature), "Only FeatureMaps allowed"); //$NON-NLS-1$
+    IListMapping mapping = doCreateFeatureMapMapping(containingClass, feature);
+    return mapping;
+  }
+
+  public abstract IListMapping doCreateListMapping(EClass containingClass, EStructuralFeature feature);
+
+  public abstract IListMapping doCreateFeatureMapMapping(EClass containingClass, EStructuralFeature feature);
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/CoreTypeMappings.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/CoreTypeMappings.java
new file mode 100644
index 0000000..f5baf6a
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/CoreTypeMappings.java
@@ -0,0 +1,882 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - bug 271444: [DB] Multiple refactorings
+ *    Stefan Winkler - bug 275303: [DB] DBStore does not handle BIG_INTEGER and BIG_DECIMAL
+ *    Kai Schlamp - bug 282976: [DB] Influence Mappings through EAnnotations
+ *    Stefan Winkler - bug 282976: [DB] Influence Mappings through EAnnotations
+ *    Stefan Winkler - bug 285270: [DB] Support XSD based models
+ *    Stefan Winkler - Bug 285426: [DB] Implement user-defined typeMapping support
+ */
+package org.eclipse.emf.cdo.server.internal.db.mapping;
+
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.lob.CDOBlob;
+import org.eclipse.emf.cdo.common.lob.CDOClob;
+import org.eclipse.emf.cdo.common.lob.CDOLobUtil;
+import org.eclipse.emf.cdo.common.revision.CDORevisionData;
+import org.eclipse.emf.cdo.etypes.EtypesPackage;
+import org.eclipse.emf.cdo.server.db.IIDHandler;
+import org.eclipse.emf.cdo.server.db.mapping.AbstractTypeMapping;
+import org.eclipse.emf.cdo.server.db.mapping.AbstractTypeMappingFactory;
+import org.eclipse.emf.cdo.server.db.mapping.ITypeMapping;
+
+import org.eclipse.net4j.db.DBType;
+import org.eclipse.net4j.util.HexUtil;
+import org.eclipse.net4j.util.factory.ProductCreationException;
+
+import org.eclipse.emf.common.util.Enumerator;
+import org.eclipse.emf.ecore.EDataType;
+import org.eclipse.emf.ecore.EEnum;
+import org.eclipse.emf.ecore.EEnumLiteral;
+import org.eclipse.emf.ecore.EFactory;
+import org.eclipse.emf.ecore.EcorePackage;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Timestamp;
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * This is a default implementation for the {@link ITypeMapping} interface which provides default behavor for all common
+ * types.
+ * 
+ * @author Eike Stepper
+ */
+public class CoreTypeMappings
+{
+  public static final String ID_PREFIX = "org.eclipse.emf.cdo.server.db.CoreTypeMappings";
+
+  /**
+   * @author Eike Stepper
+   */
+  public static class TMEnum extends AbstractTypeMapping
+  {
+    public static final Factory FACTORY = new Factory(TypeMappingUtil.createDescriptor(ID_PREFIX + ".Enum",
+        EcorePackage.eINSTANCE.getEEnum(), DBType.INTEGER));
+
+    @Override
+    public Object getResultSetValue(ResultSet resultSet) throws SQLException
+    {
+      // see Bug 271941
+      return resultSet.getInt(getField().getName());
+      // EEnum type = (EEnum)getFeature().getEType();
+      // int value = resultSet.getInt(column);
+      // return type.getEEnumLiteral(value);
+    }
+
+    @Override
+    protected Object getDefaultValue()
+    {
+      EEnum eenum = (EEnum)getFeature().getEType();
+
+      String defaultValueLiteral = getFeature().getDefaultValueLiteral();
+      if (defaultValueLiteral != null)
+      {
+        EEnumLiteral literal = eenum.getEEnumLiteralByLiteral(defaultValueLiteral);
+        return literal.getValue();
+      }
+
+      Enumerator enumerator = (Enumerator)eenum.getDefaultValue();
+      return enumerator.getValue();
+    }
+
+    /**
+     * @author Eike Stepper
+     */
+    public static class Factory extends AbstractTypeMappingFactory
+    {
+      public Factory(Descriptor descriptor)
+      {
+        super(descriptor);
+      }
+
+      @Override
+      public ITypeMapping create(String description) throws ProductCreationException
+      {
+        return new TMEnum();
+      }
+    }
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  public static class TMString extends AbstractTypeMapping
+  {
+    public static final Factory FACTORY_VARCHAR = new Factory(TypeMappingUtil.createDescriptor(ID_PREFIX
+        + ".StringVarchar", EcorePackage.eINSTANCE.getEString(), DBType.VARCHAR));
+
+    public static final Factory FACTORY_LONG_VARCHAR = new Factory(TypeMappingUtil.createDescriptor(ID_PREFIX
+        + ".StringLongVarchar", EcorePackage.eINSTANCE.getEString(), DBType.LONGVARCHAR));
+
+    public static final Factory FACTORY_CLOB = new Factory(TypeMappingUtil.createDescriptor(ID_PREFIX + ".StringClob",
+        EcorePackage.eINSTANCE.getEString(), DBType.CLOB));
+
+    @Override
+    public Object getResultSetValue(ResultSet resultSet) throws SQLException
+    {
+      return resultSet.getString(getField().getName());
+    }
+
+    /**
+     * @author Eike Stepper
+     */
+    public static class Factory extends AbstractTypeMappingFactory
+    {
+      public Factory(Descriptor descriptor)
+      {
+        super(descriptor);
+      }
+
+      @Override
+      public ITypeMapping create(String description) throws ProductCreationException
+      {
+        return new TMString();
+      }
+    }
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  public static class TMBlob extends AbstractTypeMapping
+  {
+    public static final Factory FACTORY_VARCHAR = new Factory(TypeMappingUtil.createDescriptor(ID_PREFIX
+        + ".BlobStream", EtypesPackage.eINSTANCE.getBlob(), DBType.VARCHAR));
+
+    public static final Factory FACTORY_LONG_VARCHAR = new Factory(TypeMappingUtil.createDescriptor(ID_PREFIX
+        + ".BlobStreamLongVarchar", EtypesPackage.eINSTANCE.getBlob(), DBType.LONGVARCHAR));
+
+    @Override
+    protected void doSetValue(PreparedStatement stmt, int index, Object value) throws SQLException
+    {
+      CDOBlob blob = (CDOBlob)value;
+      stmt.setString(index, HexUtil.bytesToHex(blob.getID()) + "-" + blob.getSize());
+    }
+
+    @Override
+    public Object getResultSetValue(ResultSet resultSet) throws SQLException
+    {
+      String str = resultSet.getString(getField().getName());
+      if (str == null)
+      {
+        return null;
+      }
+      
+      int pos = str.indexOf('-');
+
+      byte[] id = HexUtil.hexToBytes(str.substring(0, pos));
+      long size = Long.parseLong(str.substring(pos + 1));
+      return CDOLobUtil.createBlob(id, size);
+    }
+
+    /**
+     * @author Eike Stepper
+     */
+    public static class Factory extends AbstractTypeMappingFactory
+    {
+      public Factory(Descriptor descriptor)
+      {
+        super(descriptor);
+      }
+
+      @Override
+      public ITypeMapping create(String description) throws ProductCreationException
+      {
+        return new TMBlob();
+      }
+    }
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  public static class TMClob extends AbstractTypeMapping
+  {
+    public static final Factory FACTORY_VARCHAR = new Factory(TypeMappingUtil.createDescriptor(ID_PREFIX
+        + ".ClobStream", EtypesPackage.eINSTANCE.getClob(), DBType.VARCHAR));
+
+    public static final Factory FACTORY_LONG_VARCHAR = new Factory(TypeMappingUtil.createDescriptor(ID_PREFIX
+        + ".ClobStreamLongVarchar", EtypesPackage.eINSTANCE.getClob(), DBType.LONGVARCHAR));
+
+    @Override
+    protected void doSetValue(PreparedStatement stmt, int index, Object value) throws SQLException
+    {
+      CDOClob clob = (CDOClob)value;
+      stmt.setString(index, HexUtil.bytesToHex(clob.getID()) + "-" + clob.getSize());
+    }
+
+    @Override
+    public Object getResultSetValue(ResultSet resultSet) throws SQLException
+    {
+      String str = resultSet.getString(getField().getName());
+      if (str == null)
+      {
+        return null;
+      }
+      
+      int pos = str.indexOf('-');
+
+      byte[] id = HexUtil.hexToBytes(str.substring(0, pos));
+      long size = Long.parseLong(str.substring(pos + 1));
+      return CDOLobUtil.createClob(id, size);
+    }
+
+    /**
+     * @author Eike Stepper
+     */
+    public static class Factory extends AbstractTypeMappingFactory
+    {
+      public Factory(Descriptor descriptor)
+      {
+        super(descriptor);
+      }
+
+      @Override
+      public ITypeMapping create(String description) throws ProductCreationException
+      {
+        return new TMClob();
+      }
+    }
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  public static class TMShort extends AbstractTypeMapping
+  {
+    public static final Factory FACTORY = new Factory(TypeMappingUtil.createDescriptor(ID_PREFIX + ".Short",
+        EcorePackage.eINSTANCE.getEShort(), DBType.SMALLINT));
+
+    public static final Factory FACTORY_OBJECT = new Factory(TypeMappingUtil.createDescriptor(ID_PREFIX
+        + ".ShortObject", EcorePackage.eINSTANCE.getEShortObject(), DBType.SMALLINT));
+
+    @Override
+    public Object getResultSetValue(ResultSet resultSet) throws SQLException
+    {
+      return resultSet.getShort(getField().getName());
+    }
+
+    /**
+     * @author Eike Stepper
+     */
+    public static class Factory extends AbstractTypeMappingFactory
+    {
+      public Factory(Descriptor descriptor)
+      {
+        super(descriptor);
+      }
+
+      @Override
+      public ITypeMapping create(String description) throws ProductCreationException
+      {
+        return new TMShort();
+      }
+    }
+  }
+
+  /**
+   * @author Eike Stepper <br>
+   */
+  public static class TMObject extends AbstractTypeMapping
+  {
+    @Override
+    public Object getResultSetValue(ResultSet resultSet) throws SQLException
+    {
+      IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+      CDOID id = idHandler.getCDOID(resultSet, getField().getName());
+
+      if (id == null && getFeature().isUnsettable())
+      {
+        return CDORevisionData.NIL;
+      }
+
+      return id;
+    }
+
+    @Override
+    protected void doSetValue(PreparedStatement stmt, int index, Object value) throws SQLException
+    {
+      IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+      idHandler.setCDOID(stmt, index, (CDOID)value);
+    }
+
+    /**
+     * @author Eike Stepper
+     */
+    public static class Factory extends AbstractTypeMappingFactory
+    {
+      public Factory(Descriptor descriptor)
+      {
+        super(descriptor);
+      }
+
+      @Override
+      public ITypeMapping create(String description) throws ProductCreationException
+      {
+        return new TMObject();
+      }
+    }
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  public static class TMLong extends AbstractTypeMapping
+  {
+    public static final Factory FACTORY = new Factory(TypeMappingUtil.createDescriptor(ID_PREFIX + ".Long",
+        EcorePackage.eINSTANCE.getELong(), DBType.BIGINT));
+
+    public static final Factory FACTORY_OBJECT = new Factory(TypeMappingUtil.createDescriptor(
+        ID_PREFIX + ".LongObject", EcorePackage.eINSTANCE.getELongObject(), DBType.BIGINT));
+
+    @Override
+    public Object getResultSetValue(ResultSet resultSet) throws SQLException
+    {
+      return resultSet.getLong(getField().getName());
+    }
+
+    /**
+     * @author Eike Stepper
+     */
+    public static class Factory extends AbstractTypeMappingFactory
+    {
+      public Factory(Descriptor descriptor)
+      {
+        super(descriptor);
+      }
+
+      @Override
+      public ITypeMapping create(String description) throws ProductCreationException
+      {
+        return new TMLong();
+      }
+    }
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  public static class TMInteger extends AbstractTypeMapping
+  {
+    public static final Factory FACTORY = new Factory(TypeMappingUtil.createDescriptor(ID_PREFIX + ".Integer",
+        EcorePackage.eINSTANCE.getEInt(), DBType.INTEGER));
+
+    public static final Factory FACTORY_OBJECT = new Factory(TypeMappingUtil.createDescriptor(ID_PREFIX
+        + ".IntegerObject", EcorePackage.eINSTANCE.getEIntegerObject(), DBType.INTEGER));
+
+    @Override
+    public Object getResultSetValue(ResultSet resultSet) throws SQLException
+    {
+      return resultSet.getInt(getField().getName());
+    }
+
+    /**
+     * @author Eike Stepper
+     */
+    public static class Factory extends AbstractTypeMappingFactory
+    {
+      public Factory(Descriptor descriptor)
+      {
+        super(descriptor);
+      }
+
+      @Override
+      public ITypeMapping create(String description) throws ProductCreationException
+      {
+        return new TMInteger();
+      }
+    }
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  public static class TMFloat extends AbstractTypeMapping
+  {
+    public static final Factory FACTORY = new Factory(TypeMappingUtil.createDescriptor(ID_PREFIX + ".Float",
+        EcorePackage.eINSTANCE.getEFloat(), DBType.FLOAT));
+
+    public static final Factory FACTORY_OBJECT = new Factory(TypeMappingUtil.createDescriptor(ID_PREFIX
+        + ".FloatObject", EcorePackage.eINSTANCE.getEFloatObject(), DBType.FLOAT));
+
+    @Override
+    public Object getResultSetValue(ResultSet resultSet) throws SQLException
+    {
+      return resultSet.getFloat(getField().getName());
+    }
+
+    /**
+     * @author Eike Stepper
+     */
+    public static class Factory extends AbstractTypeMappingFactory
+    {
+      public Factory(Descriptor descriptor)
+      {
+        super(descriptor);
+      }
+
+      @Override
+      public ITypeMapping create(String description) throws ProductCreationException
+      {
+        return new TMFloat();
+      }
+    }
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  public static class TMDouble extends AbstractTypeMapping
+  {
+    public static final Factory FACTORY = new Factory(TypeMappingUtil.createDescriptor(ID_PREFIX + ".Double",
+        EcorePackage.eINSTANCE.getEDouble(), DBType.DOUBLE));
+
+    public static final Factory FACTORY_OBJECT = new Factory(TypeMappingUtil.createDescriptor(ID_PREFIX
+        + ".DoubleObject", EcorePackage.eINSTANCE.getEDoubleObject(), DBType.DOUBLE));
+
+    @Override
+    public Object getResultSetValue(ResultSet resultSet) throws SQLException
+    {
+      return resultSet.getDouble(getField().getName());
+    }
+
+    /**
+     * @author Eike Stepper
+     */
+    public static class Factory extends AbstractTypeMappingFactory
+    {
+      public Factory(Descriptor descriptor)
+      {
+        super(descriptor);
+      }
+
+      @Override
+      public ITypeMapping create(String description) throws ProductCreationException
+      {
+        return new TMDouble();
+      }
+    }
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  public static class TMDate2Timestamp extends AbstractTypeMapping
+  {
+    public static final Factory FACTORY = new Factory(TypeMappingUtil.createDescriptor(ID_PREFIX + ".Timestamp",
+        EcorePackage.eINSTANCE.getEDate(), DBType.TIMESTAMP));
+
+    @Override
+    public Object getResultSetValue(ResultSet resultSet) throws SQLException
+    {
+      return resultSet.getTimestamp(getField().getName());
+    }
+
+    @Override
+    protected void doSetValue(PreparedStatement stmt, int index, Object value) throws SQLException
+    {
+      stmt.setTimestamp(index, new Timestamp(((Date)value).getTime()));
+    }
+
+    /**
+     * @author Eike Stepper
+     */
+    public static class Factory extends AbstractTypeMappingFactory
+    {
+      public Factory(Descriptor descriptor)
+      {
+        super(descriptor);
+      }
+
+      @Override
+      public ITypeMapping create(String description) throws ProductCreationException
+      {
+        return new TMDate2Timestamp();
+      }
+    }
+  }
+
+  /**
+   * @author Heiko Ahlig
+   */
+  public static class TMDate2Date extends AbstractTypeMapping
+  {
+    public static final Factory FACTORY = new Factory(TypeMappingUtil.createDescriptor(ID_PREFIX + ".Date",
+        EcorePackage.eINSTANCE.getEDate(), DBType.DATE));
+
+    @Override
+    public Object getResultSetValue(ResultSet resultSet) throws SQLException
+    {
+      return resultSet.getDate(getField().getName(), Calendar.getInstance());
+    }
+
+    /**
+     * @author Eike Stepper
+     */
+    public static class Factory extends AbstractTypeMappingFactory
+    {
+      public Factory(Descriptor descriptor)
+      {
+        super(descriptor);
+      }
+
+      @Override
+      public ITypeMapping create(String description) throws ProductCreationException
+      {
+        return new TMDate2Date();
+      }
+    }
+  }
+
+  /**
+   * @author Heiko Ahlig
+   */
+  public static class TMDate2Time extends AbstractTypeMapping
+  {
+    public static final Factory FACTORY = new Factory(TypeMappingUtil.createDescriptor(ID_PREFIX + ".Time",
+        EcorePackage.eINSTANCE.getEDate(), DBType.TIME));
+
+    @Override
+    public Object getResultSetValue(ResultSet resultSet) throws SQLException
+    {
+      return resultSet.getTime(getField().getName(), Calendar.getInstance());
+    }
+
+    /**
+     * @author Eike Stepper
+     */
+    public static class Factory extends AbstractTypeMappingFactory
+    {
+      public Factory(Descriptor descriptor)
+      {
+        super(descriptor);
+      }
+
+      @Override
+      public ITypeMapping create(String description) throws ProductCreationException
+      {
+        return new TMDate2Time();
+      }
+    }
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  public static class TMCharacter extends AbstractTypeMapping
+  {
+    public static final Factory FACTORY = new Factory(TypeMappingUtil.createDescriptor(ID_PREFIX + ".Character",
+        EcorePackage.eINSTANCE.getEChar(), DBType.CHAR));
+
+    public static final Factory FACTORY_OBJECT = new Factory(TypeMappingUtil.createDescriptor(ID_PREFIX
+        + ".CharacterObject", EcorePackage.eINSTANCE.getECharacterObject(), DBType.CHAR));
+
+    @Override
+    public Object getResultSetValue(ResultSet resultSet) throws SQLException
+    {
+      String str = resultSet.getString(getField().getName());
+      if (resultSet.wasNull())
+      {
+        return getFeature().isUnsettable() ? CDORevisionData.NIL : null;
+      }
+
+      return str.charAt(0);
+    }
+
+    @Override
+    protected void doSetValue(PreparedStatement stmt, int index, Object value) throws SQLException
+    {
+      stmt.setString(index, ((Character)value).toString());
+    }
+
+    /**
+     * @author Eike Stepper
+     */
+    public static class Factory extends AbstractTypeMappingFactory
+    {
+      public Factory(Descriptor descriptor)
+      {
+        super(descriptor);
+      }
+
+      @Override
+      public ITypeMapping create(String description) throws ProductCreationException
+      {
+        return new TMCharacter();
+      }
+    }
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  public static class TMByte extends AbstractTypeMapping
+  {
+    public static final Factory FACTORY = new Factory(TypeMappingUtil.createDescriptor(ID_PREFIX + ".Byte",
+        EcorePackage.eINSTANCE.getEByte(), DBType.SMALLINT));
+
+    public static final Factory FACTORY_OBJECT = new Factory(TypeMappingUtil.createDescriptor(
+        ID_PREFIX + ".ByteObject", EcorePackage.eINSTANCE.getEByteObject(), DBType.SMALLINT));
+
+    @Override
+    public Object getResultSetValue(ResultSet resultSet) throws SQLException
+    {
+      return resultSet.getByte(getField().getName());
+    }
+
+    /**
+     * @author Eike Stepper
+     */
+    public static class Factory extends AbstractTypeMappingFactory
+    {
+      public Factory(Descriptor descriptor)
+      {
+        super(descriptor);
+      }
+
+      @Override
+      public ITypeMapping create(String description) throws ProductCreationException
+      {
+        return new TMByte();
+      }
+    }
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  public static class TMBytes extends AbstractTypeMapping
+  {
+    public static final Factory FACTORY = new Factory(TypeMappingUtil.createDescriptor(ID_PREFIX + ".ByteArray",
+        EcorePackage.eINSTANCE.getEByteArray(), DBType.BLOB));
+
+    @Override
+    public Object getResultSetValue(ResultSet resultSet) throws SQLException
+    {
+      return resultSet.getBytes(getField().getName());
+    }
+
+    /**
+     * @author Eike Stepper
+     */
+    public static class Factory extends AbstractTypeMappingFactory
+    {
+      public Factory(Descriptor descriptor)
+      {
+        super(descriptor);
+      }
+
+      @Override
+      public ITypeMapping create(String description) throws ProductCreationException
+      {
+        return new TMBytes();
+      }
+    }
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  public static class TMBoolean extends AbstractTypeMapping
+  {
+    public static final Factory FACTORY = new Factory(TypeMappingUtil.createDescriptor(ID_PREFIX + ".Boolean",
+        EcorePackage.eINSTANCE.getEBoolean(), DBType.BOOLEAN));
+
+    public static final Factory FACTORY_OBJECT = new Factory(TypeMappingUtil.createDescriptor(ID_PREFIX
+        + ".BooleanObject", EcorePackage.eINSTANCE.getEBooleanObject(), DBType.BOOLEAN));
+
+    public static final Factory FACTORY_SMALLINT = new Factory(TypeMappingUtil.createDescriptor(ID_PREFIX
+        + ".Boolean_SMALLINT", EcorePackage.eINSTANCE.getEBoolean(), DBType.SMALLINT));
+
+    public static final Factory FACTORY_OBJECT_SMALLINT = new Factory(TypeMappingUtil.createDescriptor(ID_PREFIX
+        + ".BooleanObject_SMALLINT", EcorePackage.eINSTANCE.getEBooleanObject(), DBType.SMALLINT));
+
+    @Override
+    public Object getResultSetValue(ResultSet resultSet) throws SQLException
+    {
+      return resultSet.getBoolean(getField().getName());
+    }
+
+    /**
+     * @author Eike Stepper
+     */
+    public static class Factory extends AbstractTypeMappingFactory
+    {
+      public Factory(Descriptor descriptor)
+      {
+        super(descriptor);
+      }
+
+      @Override
+      public ITypeMapping create(String description) throws ProductCreationException
+      {
+        return new TMBoolean();
+      }
+    }
+  }
+
+  /**
+   * @author Stefan Winkler
+   */
+  public static class TMBigInteger extends AbstractTypeMapping
+  {
+    public static final Factory FACTORY = new Factory(TypeMappingUtil.createDescriptor(ID_PREFIX + ".BigInteger",
+        EcorePackage.eINSTANCE.getEBigInteger(), DBType.VARCHAR));
+
+    public static final Factory FACTORY_LONG_VARCHAR = new Factory(TypeMappingUtil.createDescriptor(ID_PREFIX
+        + ".BigIntegerLongVarChar", EcorePackage.eINSTANCE.getEBigInteger(), DBType.LONGVARCHAR));
+
+    @Override
+    protected Object getResultSetValue(ResultSet resultSet) throws SQLException
+    {
+      String val = resultSet.getString(getField().getName());
+
+      if (resultSet.wasNull())
+      {
+        return getFeature().isUnsettable() ? CDORevisionData.NIL : null;
+      }
+
+      return new BigInteger(val);
+    }
+
+    @Override
+    protected void doSetValue(PreparedStatement stmt, int index, Object value) throws SQLException
+    {
+      stmt.setString(index, ((BigInteger)value).toString());
+    }
+
+    /**
+     * @author Eike Stepper
+     */
+    public static class Factory extends AbstractTypeMappingFactory
+    {
+      public Factory(Descriptor descriptor)
+      {
+        super(descriptor);
+      }
+
+      @Override
+      public ITypeMapping create(String description) throws ProductCreationException
+      {
+        return new TMBigInteger();
+      }
+    }
+  }
+
+  /**
+   * @author Stefan Winkler
+   */
+  public static class TMBigDecimal extends AbstractTypeMapping
+  {
+    public static final Factory FACTORY = new Factory(TypeMappingUtil.createDescriptor(ID_PREFIX + ".BigDecimal",
+        EcorePackage.eINSTANCE.getEBigDecimal(), DBType.VARCHAR));
+
+    public static final Factory FACTORY_LONG_VARCHAR = new Factory(TypeMappingUtil.createDescriptor(ID_PREFIX
+        + ".BigDecimalLongVarchar", EcorePackage.eINSTANCE.getEBigDecimal(), DBType.LONGVARCHAR));
+
+    @Override
+    protected Object getResultSetValue(ResultSet resultSet) throws SQLException
+    {
+      String val = resultSet.getString(getField().getName());
+
+      if (resultSet.wasNull())
+      {
+        return getFeature().isUnsettable() ? CDORevisionData.NIL : null;
+      }
+
+      return new BigDecimal(val);
+    }
+
+    @Override
+    protected void doSetValue(PreparedStatement stmt, int index, Object value) throws SQLException
+    {
+      stmt.setString(index, ((BigDecimal)value).toPlainString());
+    }
+
+    /**
+     * @author Eike Stepper
+     */
+    public static class Factory extends AbstractTypeMappingFactory
+    {
+      public Factory(Descriptor descriptor)
+      {
+        super(descriptor);
+      }
+
+      @Override
+      public ITypeMapping create(String description) throws ProductCreationException
+      {
+        return new TMBigDecimal();
+      }
+    }
+  }
+
+  /**
+   * @author Stefan Winkler
+   */
+  public static class TMCustom extends AbstractTypeMapping
+  {
+    public static final Factory FACTORY_VARCHAR = new Factory(TypeMappingUtil.createDescriptor(ID_PREFIX
+        + ".CustomVarchar", EcorePackage.eINSTANCE.getEDataType(), DBType.VARCHAR));
+
+    public static final Factory FACTORY_LONG_VARCHAR = new Factory(TypeMappingUtil.createDescriptor(ID_PREFIX
+        + ".CustomLongVarchar", EcorePackage.eINSTANCE.getEDataType(), DBType.LONGVARCHAR));
+
+    public static final Factory FACTORY_CLOB = new Factory(TypeMappingUtil.createDescriptor(ID_PREFIX + ".CustomClob",
+        EcorePackage.eINSTANCE.getEDataType(), DBType.CLOB));
+
+    @Override
+    protected Object getResultSetValue(ResultSet resultSet) throws SQLException
+    {
+      String val = resultSet.getString(getField().getName());
+      if (resultSet.wasNull())
+      {
+        return getFeature().isUnsettable() ? CDORevisionData.NIL : null;
+      }
+
+      return val;
+    }
+
+    @Override
+    protected Object getDefaultValue()
+    {
+      Object defaultValue = getFeature().getDefaultValue();
+      if (defaultValue == null)
+      {
+        return null;
+      }
+      
+      EFactory factory = getFeature().getEType().getEPackage().getEFactoryInstance();
+      return factory.convertToString((EDataType)getFeature().getEType(), defaultValue);
+    }
+
+    /**
+     * @author Eike Stepper
+     */
+    public static class Factory extends AbstractTypeMappingFactory
+    {
+      public Factory(Descriptor descriptor)
+      {
+        super(descriptor);
+      }
+
+      @Override
+      public ITypeMapping create(String description) throws ProductCreationException
+      {
+        return new TMCustom();
+      }
+    }
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/TypeMappingDescriptor.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/TypeMappingDescriptor.java
new file mode 100644
index 0000000..f47075d
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/TypeMappingDescriptor.java
@@ -0,0 +1,65 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Stefan Winkler - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server.internal.db.mapping;
+
+import org.eclipse.emf.cdo.server.db.mapping.ITypeMapping;
+
+import org.eclipse.net4j.db.DBType;
+
+import org.eclipse.emf.ecore.EClassifier;
+
+/**
+ * @author Stefan Winkler
+ */
+public class TypeMappingDescriptor implements ITypeMapping.Descriptor
+{
+  private String id;
+
+  private String factoryType;
+
+  private EClassifier eClassifier;
+
+  private DBType dbType;
+
+  public TypeMappingDescriptor(String id, String factoryType, EClassifier eClassifier, DBType dbType)
+  {
+    this.id = id;
+    this.factoryType = factoryType;
+    this.eClassifier = eClassifier;
+    this.dbType = dbType;
+  }
+
+  public String getID()
+  {
+    return id;
+  }
+
+  public String getFactoryType()
+  {
+    return factoryType;
+  }
+
+  public EClassifier getEClassifier()
+  {
+    return eClassifier;
+  }
+
+  public DBType getDBType()
+  {
+    return dbType;
+  }
+
+  @Override
+  public String toString()
+  {
+    return "TypeMappingDescriptor [" + factoryType + "]";
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/TypeMappingRegistry.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/TypeMappingRegistry.java
new file mode 100644
index 0000000..096e2c9
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/TypeMappingRegistry.java
@@ -0,0 +1,447 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Stefan Winkler - initial API and implementation
+ *    Stefan Winkler - Bug 285426: [DB] Implement user-defined typeMapping support
+ */
+package org.eclipse.emf.cdo.server.internal.db.mapping;
+
+import org.eclipse.emf.cdo.common.model.CDOModelUtil;
+import org.eclipse.emf.cdo.etypes.EtypesPackage;
+import org.eclipse.emf.cdo.server.db.IIDHandler;
+import org.eclipse.emf.cdo.server.db.mapping.IMappingStrategy;
+import org.eclipse.emf.cdo.server.db.mapping.ITypeMapping;
+import org.eclipse.emf.cdo.server.internal.db.DBAnnotation;
+import org.eclipse.emf.cdo.server.internal.db.bundle.OM;
+import org.eclipse.emf.cdo.server.internal.db.mapping.TypeMappingUtil.FactoryTypeParserException;
+import org.eclipse.emf.cdo.server.internal.db.messages.Messages;
+
+import org.eclipse.net4j.db.DBType;
+import org.eclipse.net4j.db.IDBAdapter;
+import org.eclipse.net4j.util.collection.Pair;
+import org.eclipse.net4j.util.container.ContainerEvent;
+import org.eclipse.net4j.util.container.IContainerDelta;
+import org.eclipse.net4j.util.container.IContainerDelta.Kind;
+import org.eclipse.net4j.util.container.IManagedContainer;
+import org.eclipse.net4j.util.container.IPluginContainer;
+import org.eclipse.net4j.util.event.IEvent;
+import org.eclipse.net4j.util.event.IListener;
+import org.eclipse.net4j.util.factory.IFactory;
+import org.eclipse.net4j.util.factory.IFactoryKey;
+import org.eclipse.net4j.util.om.trace.ContextTracer;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EClassifier;
+import org.eclipse.emf.ecore.EEnum;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.EcorePackage;
+
+import java.text.MessageFormat;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+/**
+ * An implementation of both the Registry and Provider interfaces for type mappings. This class is a singleton which
+ * keeps itself in sync with the global factory registry. It reads the available factoryTypes for the type mappings
+ * product type and populates indexes which make it easier to determine and look up the correct factories for a needed
+ * type mapping.
+ * 
+ * @author Stefan Winkler
+ */
+public class TypeMappingRegistry implements ITypeMapping.Registry, ITypeMapping.Provider
+{
+  private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG, TypeMappingRegistry.class);
+
+  /**
+   * Contains a map from model types to db types which represent default mappings. (I.e., if a model element without db
+   * type annotation is encountered, this map is consulted to retrieve the default type mapping. This map is populated
+   * on a come-first basis. The first mapping for a particular {@link EClassifier} is set as default.
+   */
+  private Map<EClassifier, DBType> classifierDefaultMapping;
+
+  /**
+   * The main TypeMapping index. For any known pair of model and db types the {@link ITypeMapping.Descriptor} is
+   * registered here.
+   */
+  private Map<Pair<EClassifier, DBType>, ITypeMapping.Descriptor> typeMappingByTypes;
+
+  /**
+   * ID-based index. Can be used to lookup an {@link ITypeMapping.Descriptor} for a given ID.
+   */
+  private Map<String, ITypeMapping.Descriptor> typeMappingsById;
+
+  /**
+   * A set of all known mapped DBTypes. This is needed for the feature map mappings.
+   */
+  private Set<DBType> defaultFeatureMapDBTypes;
+
+  /**
+   * A populator which is used to keep the registry in sync with the registered factories of the
+   * {@link IManagedContainer}.
+   */
+  private RegistryPopulator populator = new RegistryPopulator();
+
+  public TypeMappingRegistry()
+  {
+    init();
+  }
+
+  public void init()
+  {
+    populator.disconnect();
+
+    defaultFeatureMapDBTypes = new HashSet<DBType>();
+    typeMappingsById = new HashMap<String, ITypeMapping.Descriptor>();
+    typeMappingByTypes = new HashMap<Pair<EClassifier, DBType>, ITypeMapping.Descriptor>();
+    classifierDefaultMapping = new HashMap<EClassifier, DBType>();
+
+    registerCoreTypeMappings();
+    populator.connect();
+  }
+
+  /**
+   * Register builtin type mapping factories
+   */
+  private void registerCoreTypeMappings()
+  {
+    IManagedContainer container = getContainer();
+    container.registerFactory(CoreTypeMappings.TMBigDecimal.FACTORY);
+    container.registerFactory(CoreTypeMappings.TMBigDecimal.FACTORY_LONG_VARCHAR);
+    container.registerFactory(CoreTypeMappings.TMBigInteger.FACTORY);
+    container.registerFactory(CoreTypeMappings.TMBigInteger.FACTORY_LONG_VARCHAR);
+    container.registerFactory(CoreTypeMappings.TMBoolean.FACTORY);
+    container.registerFactory(CoreTypeMappings.TMBoolean.FACTORY_SMALLINT);
+    container.registerFactory(CoreTypeMappings.TMBoolean.FACTORY_OBJECT);
+    container.registerFactory(CoreTypeMappings.TMBoolean.FACTORY_OBJECT_SMALLINT);
+    container.registerFactory(CoreTypeMappings.TMByte.FACTORY);
+    container.registerFactory(CoreTypeMappings.TMByte.FACTORY_OBJECT);
+    container.registerFactory(CoreTypeMappings.TMBytes.FACTORY);
+    container.registerFactory(CoreTypeMappings.TMCharacter.FACTORY);
+    container.registerFactory(CoreTypeMappings.TMCharacter.FACTORY_OBJECT);
+    container.registerFactory(CoreTypeMappings.TMCustom.FACTORY_VARCHAR);
+    container.registerFactory(CoreTypeMappings.TMCustom.FACTORY_CLOB);
+    container.registerFactory(CoreTypeMappings.TMCustom.FACTORY_LONG_VARCHAR);
+    container.registerFactory(CoreTypeMappings.TMDate2Date.FACTORY);
+    container.registerFactory(CoreTypeMappings.TMDate2Time.FACTORY);
+    container.registerFactory(CoreTypeMappings.TMDate2Timestamp.FACTORY);
+    container.registerFactory(CoreTypeMappings.TMDouble.FACTORY);
+    container.registerFactory(CoreTypeMappings.TMDouble.FACTORY_OBJECT);
+    container.registerFactory(CoreTypeMappings.TMEnum.FACTORY);
+    container.registerFactory(CoreTypeMappings.TMFloat.FACTORY);
+    container.registerFactory(CoreTypeMappings.TMFloat.FACTORY_OBJECT);
+    container.registerFactory(CoreTypeMappings.TMInteger.FACTORY);
+    container.registerFactory(CoreTypeMappings.TMInteger.FACTORY_OBJECT);
+    container.registerFactory(CoreTypeMappings.TMLong.FACTORY);
+    container.registerFactory(CoreTypeMappings.TMLong.FACTORY_OBJECT);
+    container.registerFactory(CoreTypeMappings.TMShort.FACTORY);
+    container.registerFactory(CoreTypeMappings.TMShort.FACTORY_OBJECT);
+    container.registerFactory(CoreTypeMappings.TMString.FACTORY_VARCHAR);
+    container.registerFactory(CoreTypeMappings.TMString.FACTORY_CLOB);
+    container.registerFactory(CoreTypeMappings.TMString.FACTORY_LONG_VARCHAR);
+    container.registerFactory(CoreTypeMappings.TMBlob.FACTORY_VARCHAR);
+    container.registerFactory(CoreTypeMappings.TMBlob.FACTORY_LONG_VARCHAR);
+    container.registerFactory(CoreTypeMappings.TMClob.FACTORY_VARCHAR);
+    container.registerFactory(CoreTypeMappings.TMClob.FACTORY_LONG_VARCHAR);
+
+    classifierDefaultMapping.put(EcorePackage.eINSTANCE.getEDataType(), DBType.VARCHAR);
+
+    classifierDefaultMapping.put(EcorePackage.eINSTANCE.getEBigDecimal(), DBType.VARCHAR);
+    classifierDefaultMapping.put(EcorePackage.eINSTANCE.getEBigInteger(), DBType.VARCHAR);
+    classifierDefaultMapping.put(EcorePackage.eINSTANCE.getEBoolean(), DBType.BOOLEAN);
+    classifierDefaultMapping.put(EcorePackage.eINSTANCE.getEBooleanObject(), DBType.BOOLEAN);
+    classifierDefaultMapping.put(EcorePackage.eINSTANCE.getEByte(), DBType.SMALLINT);
+    classifierDefaultMapping.put(EcorePackage.eINSTANCE.getEByteObject(), DBType.SMALLINT);
+    classifierDefaultMapping.put(EcorePackage.eINSTANCE.getEByteArray(), DBType.BLOB);
+    classifierDefaultMapping.put(EcorePackage.eINSTANCE.getEChar(), DBType.CHAR);
+    classifierDefaultMapping.put(EcorePackage.eINSTANCE.getECharacterObject(), DBType.CHAR);
+    classifierDefaultMapping.put(EcorePackage.eINSTANCE.getEDate(), DBType.TIMESTAMP);
+    classifierDefaultMapping.put(EcorePackage.eINSTANCE.getEDouble(), DBType.DOUBLE);
+    classifierDefaultMapping.put(EcorePackage.eINSTANCE.getEDoubleObject(), DBType.DOUBLE);
+    classifierDefaultMapping.put(EcorePackage.eINSTANCE.getEEnum(), DBType.INTEGER);
+    classifierDefaultMapping.put(EcorePackage.eINSTANCE.getEFloat(), DBType.FLOAT);
+    classifierDefaultMapping.put(EcorePackage.eINSTANCE.getEFloatObject(), DBType.FLOAT);
+    classifierDefaultMapping.put(EcorePackage.eINSTANCE.getEInt(), DBType.INTEGER);
+    classifierDefaultMapping.put(EcorePackage.eINSTANCE.getEIntegerObject(), DBType.INTEGER);
+    classifierDefaultMapping.put(EcorePackage.eINSTANCE.getELong(), DBType.BIGINT);
+    classifierDefaultMapping.put(EcorePackage.eINSTANCE.getELongObject(), DBType.BIGINT);
+    classifierDefaultMapping.put(EcorePackage.eINSTANCE.getEShort(), DBType.SMALLINT);
+    classifierDefaultMapping.put(EcorePackage.eINSTANCE.getEShortObject(), DBType.SMALLINT);
+    classifierDefaultMapping.put(EcorePackage.eINSTANCE.getEString(), DBType.VARCHAR);
+
+    classifierDefaultMapping.put(EtypesPackage.eINSTANCE.getBlob(), DBType.VARCHAR); // TODO Should be DBType.BLOB?
+    classifierDefaultMapping.put(EtypesPackage.eINSTANCE.getClob(), DBType.VARCHAR); // TODO Should be DBType.CLOB?
+  }
+
+  protected IManagedContainer getContainer()
+  {
+    return IPluginContainer.INSTANCE;
+  }
+
+  public void registerTypeMapping(ITypeMapping.Descriptor descriptor)
+  {
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Registering {0}", descriptor);
+    }
+
+    EClassifier eClassifier = descriptor.getEClassifier();
+    DBType dbType = descriptor.getDBType();
+    Pair<EClassifier, DBType> sourceTargetPair = new Pair<EClassifier, DBType>(eClassifier, dbType);
+
+    // currently we do not support more than one typeMapping per source-target type pair
+    if (typeMappingByTypes.containsKey(sourceTargetPair))
+    {
+      OM.LOG.error(Messages.getString("TypeMappingRegistry.4"));
+      return;
+    }
+
+    if (typeMappingsById.containsKey(descriptor.getID()))
+    {
+      OM.LOG.error(MessageFormat.format(Messages.getString("TypeMappingRegistry.5"), descriptor.getID()));
+      return;
+    }
+
+    typeMappingsById.put(descriptor.getID(), descriptor);
+
+    // register first dbType for classifier as default
+    if (!classifierDefaultMapping.containsKey(eClassifier))
+    {
+      classifierDefaultMapping.put(eClassifier, dbType);
+    }
+
+    defaultFeatureMapDBTypes.add(dbType);
+
+    typeMappingByTypes.put(sourceTargetPair, descriptor);
+  }
+
+  public ITypeMapping createTypeMapping(IMappingStrategy mappingStrategy, EStructuralFeature feature)
+  {
+    ITypeMapping typeMapping = null;
+    if (feature instanceof EReference)
+    {
+      IIDHandler idHandler = mappingStrategy.getStore().getIDHandler();
+      typeMapping = idHandler.getObjectTypeMapping();
+      typeMapping.setDBType(idHandler.getDBType());
+    }
+    else
+    {
+      IDBAdapter dbAdapter = mappingStrategy.getStore().getDBAdapter();
+      DBType dbType = getDBType(feature, dbAdapter);
+
+      ITypeMapping.Descriptor descriptor = null;
+
+      String typeMappingID = DBAnnotation.TYPE_MAPPING.getValue(feature);
+      if (typeMappingID != null)
+      {
+        // lookup annotated mapping
+        descriptor = typeMappingsById.get(typeMappingID);
+
+        if (descriptor == null)
+        {
+          OM.LOG.warn(MessageFormat.format(Messages.getString("TypeMappingRegistry.2"), //
+              typeMappingID, feature.toString()));
+        }
+      }
+
+      if (descriptor == null)
+      {
+        // try to find suitable mapping by type
+        descriptor = getMappingByType(feature, dbType);
+      }
+
+      if (descriptor == null)
+      {
+        EClassifier type = getEType(feature);
+        throw new IllegalStateException(MessageFormat.format(Messages.getString("TypeMappingRegistry.1"), feature
+            .getEContainingClass().getName() + "." + feature.getName(),
+            type.getEPackage().getName() + "." + type.getName(), dbType.getKeyword()));
+      }
+
+      IFactory factory = getContainer().getFactory(ITypeMapping.Factory.PRODUCT_GROUP, descriptor.getFactoryType());
+      typeMapping = (ITypeMapping)factory.create(null);
+      typeMapping.setDBType(dbType);
+    }
+
+    typeMapping.setMappingStrategy(mappingStrategy);
+    typeMapping.setFeature(feature);
+    return typeMapping;
+  }
+
+  private EClassifier getEType(EStructuralFeature feature)
+  {
+    EClassifier classifier = feature.getEType();
+    if (classifier instanceof EEnum)
+    {
+      return EcorePackage.eINSTANCE.getEEnum();
+    }
+
+    if (classifier instanceof EClass)
+    {
+      return EcorePackage.eINSTANCE.getEClass();
+    }
+
+    EPackage ePackage = classifier.getEPackage();
+    if (CDOModelUtil.isCorePackage(ePackage))
+    {
+      return classifier;
+    }
+
+    if (CDOModelUtil.isTypesPackage(ePackage))
+    {
+      return classifier;
+    }
+
+    return EcorePackage.eINSTANCE.getEDataType();
+  }
+
+  private DBType getDBType(EStructuralFeature feature, IDBAdapter dbAdapter)
+  {
+    String typeKeyword = DBAnnotation.COLUMN_TYPE.getValue(feature);
+    if (typeKeyword != null)
+    {
+      DBType dbType = DBType.getTypeByKeyword(typeKeyword);
+      if (dbType == null)
+      {
+        throw new IllegalArgumentException("Unsupported columnType (" + typeKeyword + ") annotation of feature "
+            + feature.getName());
+      }
+
+      return dbType;
+    }
+
+    // No annotation present - lookup default DB type.
+    return getDefaultDBType(getEType(feature), dbAdapter);
+  }
+
+  private DBType getDefaultDBType(EClassifier type, IDBAdapter dbAdapter)
+  {
+    DBType result = classifierDefaultMapping.get(type);
+
+    if (result == null)
+    {
+      result = DBType.VARCHAR;
+    }
+
+    // Give the DBAdapter a chance to override the default type, if it's not supported
+    return dbAdapter.adaptType(result);
+  }
+
+  private ITypeMapping.Descriptor getMappingByType(EStructuralFeature feature, DBType dbType)
+  {
+    // First try: lookup specific mapping for the immediate type.
+    ITypeMapping.Descriptor descriptor = typeMappingByTypes.get(new Pair<EClassifier, DBType>(feature.getEType(),
+        dbType));
+
+    if (descriptor == null)
+    {
+      // Second try: lookup general mapping
+      descriptor = typeMappingByTypes.get(new Pair<EClassifier, DBType>(getEType(feature), dbType));
+      if (descriptor == null)
+      {
+        // Lookup failed. Give up
+        return null;
+      }
+    }
+
+    return descriptor;
+  }
+
+  public Collection<DBType> getDefaultFeatureMapDBTypes()
+  {
+    return defaultFeatureMapDBTypes;
+  }
+
+  /**
+   * Keeps the {@link TypeMappingRegistry} in sync with {@link IManagedContainer#getFactoryRegistry()}.
+   * 
+   * @author Stefan Winkler
+   */
+  private class RegistryPopulator implements IListener
+  {
+    private IManagedContainer container = getContainer();
+
+    public RegistryPopulator()
+    {
+    }
+
+    /**
+     * Connect to the factory registry.
+     */
+    public void connect()
+    {
+      populateTypeMappingRegistry();
+      container.getFactoryRegistry().addListener(this);
+    }
+
+    public void disconnect()
+    {
+      container.getFactoryRegistry().removeListener(this);
+    }
+
+    private void populateTypeMappingRegistry()
+    {
+      // get available factory types
+      Set<String> factoryTypes = container.getFactoryTypes(ITypeMapping.Factory.PRODUCT_GROUP);
+
+      // parse the descriptor of each factory type
+      for (String factoryType : factoryTypes)
+      {
+        registerFactoryType(factoryType);
+      }
+    }
+
+    private void registerFactoryType(String factoryType)
+    {
+      ITypeMapping.Descriptor desc;
+
+      try
+      {
+        desc = TypeMappingUtil.descriptorFromFactoryType(factoryType);
+        registerTypeMapping(desc);
+      }
+      catch (FactoryTypeParserException ex)
+      {
+        OM.LOG.warn(ex);
+      }
+    }
+
+    public void notifyEvent(IEvent event)
+    {
+      if (event instanceof ContainerEvent<?>)
+      {
+        @SuppressWarnings("unchecked")
+        ContainerEvent<Map.Entry<IFactoryKey, IFactory>> ev = (ContainerEvent<Entry<IFactoryKey, IFactory>>)event;
+
+        for (IContainerDelta<Map.Entry<IFactoryKey, IFactory>> delta : ev.getDeltas())
+        {
+          IFactoryKey key = delta.getElement().getKey();
+          if (key.getProductGroup().equals(ITypeMapping.Factory.PRODUCT_GROUP))
+          {
+            if (delta.getKind() == Kind.ADDED)
+            {
+              String factoryType = delta.getElement().getKey().getType();
+              registerFactoryType(factoryType);
+            }
+            else
+            // delta.getKind() == Kind.REMOVED
+            {
+              // XXX Runtime removal of typeMappingFactories removal of type mappings is currently not supported.
+              OM.LOG.warn(Messages.getString("TypeMappingRegistry.3"));
+            }
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/TypeMappingUtil.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/TypeMappingUtil.java
new file mode 100644
index 0000000..1bdbaa1
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/TypeMappingUtil.java
@@ -0,0 +1,113 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server.internal.db.mapping;
+
+import org.eclipse.emf.cdo.server.db.mapping.ITypeMapping;
+import org.eclipse.emf.cdo.server.internal.db.messages.Messages;
+
+import org.eclipse.net4j.db.DBType;
+
+import org.eclipse.emf.ecore.EClassifier;
+import org.eclipse.emf.ecore.EPackage;
+
+import java.text.MessageFormat;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author Stefan Winkler
+ */
+public class TypeMappingUtil
+{
+  private static final Pattern FACTORY_DESCRIPTOR_PATTERN = Pattern.compile("(.+);(.+)#(.+)->(.+)");
+
+  /**
+   * Utility class - no instantiation.
+   */
+  private TypeMappingUtil()
+  {
+  }
+
+  public static ITypeMapping.Descriptor createDescriptor(String id, EClassifier eClassifier, DBType dbType)
+  {
+    String factoryType = createFactoryType(id, eClassifier, dbType);
+    return new TypeMappingDescriptor(id, factoryType, eClassifier, dbType);
+  }
+
+  public static String createFactoryType(String id, EClassifier eClassifier, DBType dbType)
+  {
+    StringBuilder builder = new StringBuilder();
+
+    // id
+    builder.append(id);
+    builder.append(";");
+
+    // classifier
+    builder.append(eClassifier.getEPackage().getNsURI());
+    builder.append("#");
+    builder.append(eClassifier.getName());
+    builder.append("->");
+
+    // dbtype
+    builder.append(dbType.getKeyword());
+
+    return builder.toString();
+  }
+
+  public static ITypeMapping.Descriptor descriptorFromFactoryType(String factoryType) throws FactoryTypeParserException
+  {
+    Matcher matcher = FACTORY_DESCRIPTOR_PATTERN.matcher(factoryType);
+
+    if (!matcher.matches())
+    {
+      throw new FactoryTypeParserException(MessageFormat.format(Messages.getString("FactoryTypeParserException.1"),
+          factoryType));
+    }
+
+    String id = matcher.group(1);
+    String packageUri = matcher.group(2);
+    String classifierName = matcher.group(3);
+    String typeKeyword = matcher.group(4);
+
+    EPackage ePackage = EPackage.Registry.INSTANCE.getEPackage(packageUri);
+    if (ePackage == null)
+    {
+      throw new FactoryTypeParserException(MessageFormat.format(Messages.getString("FactoryTypeParserException.2"),
+          packageUri, factoryType));
+    }
+
+    EClassifier eClassifier = ePackage.getEClassifier(classifierName);
+    if (eClassifier == null)
+    {
+      throw new FactoryTypeParserException(MessageFormat.format(Messages.getString("FactoryTypeParserException.3"),
+          classifierName, factoryType));
+    }
+
+    DBType dbType = DBType.getTypeByKeyword(typeKeyword);
+    if (dbType == null)
+    {
+      throw new FactoryTypeParserException(MessageFormat.format(Messages.getString("FactoryTypeParserException.4"),
+          dbType, factoryType));
+    }
+
+    return new TypeMappingDescriptor(id, factoryType, eClassifier, dbType);
+  }
+
+  public static class FactoryTypeParserException extends Exception
+  {
+    private static final long serialVersionUID = 1L;
+
+    public FactoryTypeParserException(String desc)
+    {
+      super(desc);
+    }
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AbstractFeatureMapTableMapping.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AbstractFeatureMapTableMapping.java
new file mode 100644
index 0000000..83493b4
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AbstractFeatureMapTableMapping.java
@@ -0,0 +1,588 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - 271444: [DB] Multiple refactorings bug 271444
+ *    Christopher Albert - 254455: [DB] Support FeatureMaps bug 254455
+ *    Victor Roldan Betancort - Bug 283998: [DB] Chunk reading for multiple chunks fails
+ *    Stefan Winkler - Bug 285426: [DB] Implement user-defined typeMapping support
+ *    Stefan Winkler - Bug 329025: [DB] Support branching for range-based mapping strategy
+ */
+package org.eclipse.emf.cdo.server.internal.db.mapping.horizontal;
+
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.revision.CDOList;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionUtil;
+import org.eclipse.emf.cdo.server.IStoreAccessor.QueryXRefsContext;
+import org.eclipse.emf.cdo.server.IStoreChunkReader.Chunk;
+import org.eclipse.emf.cdo.server.db.IDBStore;
+import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
+import org.eclipse.emf.cdo.server.db.IDBStoreChunkReader;
+import org.eclipse.emf.cdo.server.db.IIDHandler;
+import org.eclipse.emf.cdo.server.db.IPreparedStatementCache;
+import org.eclipse.emf.cdo.server.db.IPreparedStatementCache.ReuseProbability;
+import org.eclipse.emf.cdo.server.db.mapping.IMappingStrategy;
+import org.eclipse.emf.cdo.server.db.mapping.ITypeMapping;
+import org.eclipse.emf.cdo.server.internal.db.CDODBSchema;
+import org.eclipse.emf.cdo.server.internal.db.bundle.OM;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+
+import org.eclipse.net4j.db.DBException;
+import org.eclipse.net4j.db.DBType;
+import org.eclipse.net4j.db.DBUtil;
+import org.eclipse.net4j.db.ddl.IDBField;
+import org.eclipse.net4j.db.ddl.IDBIndex.Type;
+import org.eclipse.net4j.db.ddl.IDBTable;
+import org.eclipse.net4j.util.ImplementationError;
+import org.eclipse.net4j.util.collection.MoveableList;
+import org.eclipse.net4j.util.om.trace.ContextTracer;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.util.FeatureMap;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This abstract base class provides basic behavior needed for mapping many-valued attributes to tables.
+ * 
+ * @author Eike Stepper
+ * @since 3.0
+ */
+public abstract class AbstractFeatureMapTableMapping extends BasicAbstractListTableMapping
+{
+  private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG, AbstractFeatureMapTableMapping.class);
+
+  /**
+   * The table of this mapping.
+   */
+  private IDBTable table;
+
+  /**
+   * The tags mapped to column names
+   */
+  private HashMap<CDOID, String> tagMap;
+
+  /**
+   * Column name Set
+   */
+  private List<String> columnNames;
+
+  /**
+   * The type mappings for the value fields.
+   */
+  private Map<CDOID, ITypeMapping> typeMappings;
+
+  // --------- SQL strings - see initSQLStrings() -----------------
+  private String sqlSelectChunksPrefix;
+
+  private String sqlOrderByIndex;
+
+  protected String sqlInsert;
+
+  private List<DBType> dbTypes;
+
+  public AbstractFeatureMapTableMapping(IMappingStrategy mappingStrategy, EClass eClass, EStructuralFeature feature)
+  {
+    super(mappingStrategy, eClass, feature);
+    initDBTypes();
+    initTable();
+    initSQLStrings();
+  }
+
+  private void initDBTypes()
+  {
+    // TODO add annotation processing here ...
+    ITypeMapping.Registry registry = getTypeMappingRegistry();
+    dbTypes = new ArrayList<DBType>(registry.getDefaultFeatureMapDBTypes());
+  }
+
+  protected ITypeMapping.Registry getTypeMappingRegistry()
+  {
+    return ITypeMapping.Registry.INSTANCE;
+  }
+
+  private void initTable()
+  {
+    IDBStore store = getMappingStrategy().getStore();
+    String tableName = getMappingStrategy().getTableName(getContainingClass(), getFeature());
+    table = store.getDBSchema().addTable(tableName);
+
+    // add fields for keys (cdo_id, version, feature_id)
+    FieldInfo[] fields = getKeyFields();
+    IDBField[] dbFields = new IDBField[fields.length];
+
+    for (int i = 0; i < fields.length; i++)
+    {
+      dbFields[i] = table.addField(fields[i].getName(), fields[i].getDbType());
+    }
+
+    // add field for list index
+    IDBField idxField = table.addField(CDODBSchema.FEATUREMAP_IDX, DBType.INTEGER);
+
+    // add field for FeatureMap tag (MetaID for Feature in CDO registry)
+    IDBField tagField = table.addField(CDODBSchema.FEATUREMAP_TAG, store.getIDHandler().getDBType());
+
+    tagMap = new HashMap<CDOID, String>();
+    typeMappings = new HashMap<CDOID, ITypeMapping>();
+    columnNames = new ArrayList<String>();
+
+    // create columns for all DBTypes
+    for (DBType type : getDBTypes())
+    {
+      String column = CDODBSchema.FEATUREMAP_VALUE + "_" + type.name();
+      table.addField(column, type);
+      columnNames.add(column);
+    }
+
+    table.addIndex(Type.NON_UNIQUE, dbFields);
+    table.addIndex(Type.NON_UNIQUE, idxField);
+    table.addIndex(Type.NON_UNIQUE, tagField);
+  }
+
+  protected abstract FieldInfo[] getKeyFields();
+
+  protected abstract void setKeyFields(PreparedStatement stmt, CDORevision revision) throws SQLException;
+
+  public Collection<IDBTable> getDBTables()
+  {
+    return Arrays.asList(table);
+  }
+
+  private void initSQLStrings()
+  {
+    String tableName = getTable().getName();
+    FieldInfo[] fields = getKeyFields();
+
+    // ---------------- SELECT to read chunks ----------------------------
+    StringBuilder builder = new StringBuilder();
+    builder.append("SELECT ");
+
+    builder.append(CDODBSchema.FEATUREMAP_TAG);
+    builder.append(", ");
+
+    Iterator<String> iter = columnNames.iterator();
+    while (iter.hasNext())
+    {
+      builder.append(iter.next());
+      if (iter.hasNext())
+      {
+        builder.append(", ");
+      }
+    }
+
+    builder.append(" FROM ");
+    builder.append(tableName);
+    builder.append(" WHERE ");
+
+    for (int i = 0; i < fields.length; i++)
+    {
+      builder.append(fields[i].getName());
+      if (i + 1 < fields.length)
+      {
+        // more to come
+        builder.append("=? AND ");
+      }
+      else
+      {
+        // last one
+        builder.append("=? ");
+      }
+    }
+
+    sqlSelectChunksPrefix = builder.toString();
+
+    sqlOrderByIndex = " ORDER BY " + CDODBSchema.FEATUREMAP_IDX; //$NON-NLS-1$
+
+    // INSERT with dynamic field name
+    // TODO: Better: universal INSERT-Statement, because of stmt caching!
+
+    // ----------------- INSERT - prefix -----------------
+    builder = new StringBuilder("INSERT INTO ");
+    builder.append(tableName);
+    builder.append(" ("); //$NON-NLS-1$
+    for (int i = 0; i < fields.length; i++)
+    {
+      builder.append(fields[i].getName());
+      builder.append(", "); //$NON-NLS-1$
+    }
+
+    for (int i = 0; i < columnNames.size(); i++)
+    {
+      builder.append(columnNames.get(i));
+      builder.append(", "); //$NON-NLS-1$
+    }
+
+    builder.append(CDODBSchema.FEATUREMAP_IDX);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_TAG);
+    builder.append(") VALUES ("); //$NON-NLS-1$
+    for (int i = 0; i < fields.length + columnNames.size(); i++)
+    {
+      builder.append("?, ");
+    }
+
+    builder.append("?, ?)");
+    sqlInsert = builder.toString();
+  }
+
+  protected List<DBType> getDBTypes()
+  {
+    return dbTypes;
+  }
+
+  protected final IDBTable getTable()
+  {
+    return table;
+  }
+
+  protected final List<String> getColumnNames()
+  {
+    return columnNames;
+  }
+
+  protected final Map<CDOID, ITypeMapping> getTypeMappings()
+  {
+    return typeMappings;
+  }
+
+  protected final Map<CDOID, String> getTagMap()
+  {
+    return tagMap;
+  }
+
+  public void readValues(IDBStoreAccessor accessor, InternalCDORevision revision, int listChunk)
+  {
+    MoveableList<Object> list = revision.getList(getFeature());
+    if (listChunk == 0 || list.size() == 0)
+    {
+      // nothing to read take shortcut
+      return;
+    }
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Reading list values for feature {0}.{1} of {2}v{3}", getContainingClass().getName(), getFeature()
+          .getName(), revision.getID(), revision.getVersion());
+    }
+
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+    ResultSet resultSet = null;
+
+    try
+    {
+      String sql = sqlSelectChunksPrefix + sqlOrderByIndex;
+      stmt = statementCache.getPreparedStatement(sql, ReuseProbability.HIGH);
+      setKeyFields(stmt, revision);
+
+      if (listChunk != CDORevision.UNCHUNKED)
+      {
+        stmt.setMaxRows(listChunk); // optimization - don't read unneeded rows.
+      }
+
+      resultSet = stmt.executeQuery();
+      int currentIndex = 0;
+
+      while ((listChunk == CDORevision.UNCHUNKED || --listChunk >= 0) && resultSet.next())
+      {
+        CDOID tag = idHandler.getCDOID(resultSet, 1);
+        Object value = getTypeMapping(tag).readValue(resultSet);
+
+        if (TRACER.isEnabled())
+        {
+          TRACER.format("Read value for index {0} from result set: {1}", list.size(), value);
+        }
+
+        list.set(currentIndex++, CDORevisionUtil.createFeatureMapEntry(getFeatureByTag(tag), value));
+      }
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex);
+    }
+    finally
+    {
+      DBUtil.close(resultSet);
+      statementCache.releasePreparedStatement(stmt);
+    }
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Reading list values done for feature {0}.{1} of {2}v{3}", getContainingClass().getName(),
+          getFeature().getName(), revision.getID(), revision.getVersion());
+    }
+  }
+
+  private void addFeature(CDOID tag)
+  {
+    EStructuralFeature modelFeature = getFeatureByTag(tag);
+
+    ITypeMapping typeMapping = getMappingStrategy().createValueMapping(modelFeature);
+    String column = CDODBSchema.FEATUREMAP_VALUE + "_" + typeMapping.getDBType();
+
+    tagMap.put(tag, column);
+    typeMapping.setDBField(table, column);
+    typeMappings.put(tag, typeMapping);
+  }
+
+  public final void readChunks(IDBStoreChunkReader chunkReader, List<Chunk> chunks, String where)
+  {
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Reading list chunk values for feature {0}.{1} of {2}v{3}", getContainingClass().getName(),
+          getFeature().getName(), chunkReader.getRevision().getID(), chunkReader.getRevision().getVersion());
+    }
+
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = chunkReader.getAccessor().getStatementCache();
+    PreparedStatement stmt = null;
+    ResultSet resultSet = null;
+
+    try
+    {
+      StringBuilder builder = new StringBuilder(sqlSelectChunksPrefix);
+      if (where != null)
+      {
+        builder.append(" AND "); //$NON-NLS-1$
+        builder.append(where);
+      }
+
+      builder.append(sqlOrderByIndex);
+
+      String sql = builder.toString();
+      stmt = statementCache.getPreparedStatement(sql, ReuseProbability.LOW);
+      setKeyFields(stmt, chunkReader.getRevision());
+
+      resultSet = stmt.executeQuery();
+
+      Chunk chunk = null;
+      int chunkSize = 0;
+      int chunkIndex = 0;
+      int indexInChunk = 0;
+
+      while (resultSet.next())
+      {
+        CDOID tag = idHandler.getCDOID(resultSet, 1);
+        Object value = getTypeMapping(tag).readValue(resultSet);
+
+        if (chunk == null)
+        {
+          chunk = chunks.get(chunkIndex++);
+          chunkSize = chunk.size();
+
+          if (TRACER.isEnabled())
+          {
+            TRACER.format("Current chunk no. {0} is [start = {1}, size = {2}]", chunkIndex - 1, chunk.getStartIndex(),
+                chunkSize);
+          }
+        }
+
+        if (TRACER.isEnabled())
+        {
+          TRACER.format("Read value for chunk index {0} from result set: {1}", indexInChunk, value);
+        }
+
+        chunk.add(indexInChunk++, CDORevisionUtil.createFeatureMapEntry(getFeatureByTag(tag), value));
+        if (indexInChunk == chunkSize)
+        {
+          if (TRACER.isEnabled())
+          {
+            TRACER.format("Chunk finished");
+          }
+
+          chunk = null;
+          indexInChunk = 0;
+        }
+      }
+
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Reading list chunk values done for feature {0}.{1} of {2}", getContainingClass().getName(),
+            getFeature(), chunkReader.getRevision());
+      }
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex);
+    }
+    finally
+    {
+      DBUtil.close(resultSet);
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  public void writeValues(IDBStoreAccessor accessor, InternalCDORevision revision)
+  {
+    CDOList values = revision.getList(getFeature());
+
+    int idx = 0;
+    for (Object element : values)
+    {
+      writeValue(accessor, revision, idx++, element);
+    }
+  }
+
+  protected final void writeValue(IDBStoreAccessor accessor, CDORevision revision, int idx, Object value)
+  {
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+
+    if (TRACER.isEnabled())
+    {
+      TRACER
+          .format(
+              "Writing value for feature {0}.{1} index {2} of {3} : {4}", getContainingClass().getName(), getFeature(), idx, revision, value); //$NON-NLS-1$
+    }
+
+    try
+    {
+      FeatureMap.Entry entry = (FeatureMap.Entry)value;
+      EStructuralFeature entryFeature = entry.getEStructuralFeature();
+      CDOID tag = getTagByFeature(entryFeature, revision.getTimeStamp());
+      String columnName = getColumnName(tag);
+
+      stmt = statementCache.getPreparedStatement(sqlInsert, ReuseProbability.HIGH);
+      setKeyFields(stmt, revision);
+      int column = getKeyFields().length + 1;
+
+      for (int i = 0; i < columnNames.size(); i++)
+      {
+        if (columnNames.get(i).equals(columnName))
+        {
+          getTypeMapping(tag).setValue(stmt, column++, entry.getValue());
+        }
+        else
+        {
+          stmt.setNull(column++, getDBTypes().get(i).getCode());
+        }
+      }
+
+      stmt.setInt(column++, idx);
+      idHandler.setCDOID(stmt, column++, tag);
+      DBUtil.update(stmt, true);
+    }
+    catch (SQLException e)
+    {
+      throw new DBException(e);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  /**
+   * Get column name (lazy)
+   * 
+   * @param tag
+   *          The feature's MetaID in CDO
+   * @return the column name where the values are stored
+   */
+  protected String getColumnName(CDOID tag)
+  {
+    String column = tagMap.get(tag);
+    if (column == null)
+    {
+      addFeature(tag);
+      column = tagMap.get(tag);
+    }
+
+    return column;
+  }
+
+  /**
+   * Get type mapping (lazy)
+   * 
+   * @param tag
+   *          The feature's MetaID in CDO
+   * @return the corresponding type mapping
+   */
+  protected ITypeMapping getTypeMapping(CDOID tag)
+  {
+    ITypeMapping typeMapping = typeMappings.get(tag);
+    if (typeMapping == null)
+    {
+      addFeature(tag);
+      typeMapping = typeMappings.get(tag);
+    }
+
+    return typeMapping;
+  }
+
+  /**
+   * @param metaID
+   * @return the column name where the values are stored
+   */
+  private EStructuralFeature getFeatureByTag(CDOID tag)
+  {
+    return (EStructuralFeature)getMappingStrategy().getStore().getMetaDataManager().getMetaInstance(tag);
+  }
+
+  /**
+   * @param feature
+   *          The EStructuralFeature
+   * @return The feature's MetaID in CDO
+   */
+  protected CDOID getTagByFeature(EStructuralFeature feature, long timeStamp)
+  {
+    return getMappingStrategy().getStore().getMetaDataManager().getMetaID(feature, timeStamp);
+  }
+
+  /**
+   * Used by subclasses to indicate which fields should be in the table. I.e. just a pair of name and DBType ...
+   * 
+   * @author Stefan Winkler
+   */
+  protected static class FieldInfo
+  {
+    private String name;
+
+    private DBType dbType;
+
+    public FieldInfo(String name, DBType dbType)
+    {
+      this.name = name;
+      this.dbType = dbType;
+    }
+
+    public String getName()
+    {
+      return name;
+    }
+
+    public DBType getDbType()
+    {
+      return dbType;
+    }
+  }
+
+  public final boolean queryXRefs(IDBStoreAccessor accessor, String mainTableName, String mainTableWhere,
+      QueryXRefsContext context, String idString)
+  {
+    /*
+     * must never be called (a feature map is not associated with an EReference feature, so XRefs are nor supported
+     * here)
+     */
+    throw new ImplementationError("Should never be called!");
+  }
+
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AbstractHorizontalClassMapping.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AbstractHorizontalClassMapping.java
new file mode 100644
index 0000000..bb500d3
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AbstractHorizontalClassMapping.java
@@ -0,0 +1,870 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - 271444: [DB] Multiple refactorings bug 271444
+ *    Stefan Winkler - 249610: [DB] Support external references (Implementation)
+ *    Stefan Winkler - Bug 329025: [DB] Support branching for range-based mapping strategy
+ */
+package org.eclipse.emf.cdo.server.internal.db.mapping.horizontal;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchManager;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.branch.CDOBranchVersion;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.model.CDOModelUtil;
+import org.eclipse.emf.cdo.common.revision.CDOList;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionHandler;
+import org.eclipse.emf.cdo.common.revision.CDORevisionManager;
+import org.eclipse.emf.cdo.eresource.EresourcePackage;
+import org.eclipse.emf.cdo.server.IRepository;
+import org.eclipse.emf.cdo.server.IStoreAccessor.QueryXRefsContext;
+import org.eclipse.emf.cdo.server.db.IDBStore;
+import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
+import org.eclipse.emf.cdo.server.db.IIDHandler;
+import org.eclipse.emf.cdo.server.db.IPreparedStatementCache;
+import org.eclipse.emf.cdo.server.db.IPreparedStatementCache.ReuseProbability;
+import org.eclipse.emf.cdo.server.db.mapping.IClassMapping;
+import org.eclipse.emf.cdo.server.db.mapping.IListMapping;
+import org.eclipse.emf.cdo.server.db.mapping.IMappingStrategy;
+import org.eclipse.emf.cdo.server.db.mapping.ITypeMapping;
+import org.eclipse.emf.cdo.server.internal.db.CDODBSchema;
+import org.eclipse.emf.cdo.server.internal.db.bundle.OM;
+import org.eclipse.emf.cdo.spi.common.commit.CDOChangeSetSegment;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDOList;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+
+import org.eclipse.net4j.db.DBException;
+import org.eclipse.net4j.db.DBType;
+import org.eclipse.net4j.db.DBUtil;
+import org.eclipse.net4j.db.ddl.IDBField;
+import org.eclipse.net4j.db.ddl.IDBIndex;
+import org.eclipse.net4j.db.ddl.IDBTable;
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+import org.eclipse.net4j.util.om.monitor.OMMonitor.Async;
+import org.eclipse.net4j.util.om.trace.ContextTracer;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.util.FeatureMapUtil;
+
+import org.eclipse.core.runtime.Assert;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author Eike Stepper
+ * @since 2.0
+ */
+public abstract class AbstractHorizontalClassMapping implements IClassMapping
+{
+  private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG, AbstractHorizontalClassMapping.class);
+
+  private EClass eClass;
+
+  private IDBTable table;
+
+  private AbstractHorizontalMappingStrategy mappingStrategy;
+
+  private List<ITypeMapping> valueMappings;
+
+  private List<IListMapping> listMappings;
+
+  private Map<EStructuralFeature, String> listSizeFields;
+
+  private Map<EStructuralFeature, String> unsettableFields;
+
+  private String sqlSelectForHandle;
+
+  private String sqlSelectForChangeSet;
+
+  public AbstractHorizontalClassMapping(AbstractHorizontalMappingStrategy mappingStrategy, EClass eClass)
+  {
+    this.mappingStrategy = mappingStrategy;
+    this.eClass = eClass;
+
+    initTable();
+    initFeatures();
+    initSQLStrings();
+  }
+
+  private void initTable()
+  {
+    IDBStore store = getMappingStrategy().getStore();
+    DBType idType = store.getIDHandler().getDBType();
+
+    String name = getMappingStrategy().getTableName(eClass);
+    table = store.getDBSchema().addTable(name);
+
+    IDBField idField = table.addField(CDODBSchema.ATTRIBUTES_ID, idType, true);
+    IDBField versionField = table.addField(CDODBSchema.ATTRIBUTES_VERSION, DBType.INTEGER, true);
+
+    IDBField branchField = addBranchingField(table);
+
+    table.addField(CDODBSchema.ATTRIBUTES_CREATED, DBType.BIGINT, true);
+    IDBField revisedField = table.addField(CDODBSchema.ATTRIBUTES_REVISED, DBType.BIGINT, true);
+    table.addField(CDODBSchema.ATTRIBUTES_RESOURCE, idType, true);
+    table.addField(CDODBSchema.ATTRIBUTES_CONTAINER, idType, true);
+    table.addField(CDODBSchema.ATTRIBUTES_FEATURE, DBType.INTEGER, true);
+
+    if (branchField != null)
+    {
+      table.addIndex(IDBIndex.Type.UNIQUE, idField, versionField, branchField);
+    }
+    else
+    {
+      table.addIndex(IDBIndex.Type.UNIQUE, idField, versionField);
+    }
+
+    table.addIndex(IDBIndex.Type.NON_UNIQUE, idField, revisedField);
+  }
+
+  protected IDBField addBranchingField(IDBTable table)
+  {
+    return null;
+  }
+
+  private void initFeatures()
+  {
+    EStructuralFeature[] features = CDOModelUtil.getAllPersistentFeatures(eClass);
+
+    if (features == null)
+    {
+      valueMappings = Collections.emptyList();
+      listMappings = Collections.emptyList();
+    }
+    else
+    {
+      valueMappings = createValueMappings(features);
+      listMappings = createListMappings(features);
+    }
+  }
+
+  private void initSQLStrings()
+  {
+    // ----------- Select all revisions (for handleRevisions) ---
+    StringBuilder builder = new StringBuilder("SELECT "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_ID);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_VERSION);
+    builder.append(" FROM "); //$NON-NLS-1$
+    builder.append(getTable());
+    sqlSelectForHandle = builder.toString();
+
+    // ----------- Select all revisions (for readChangeSet) ---
+    builder = new StringBuilder("SELECT DISTINCT "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_ID);
+    builder.append(" FROM "); //$NON-NLS-1$
+    builder.append(getTable());
+    builder.append(" WHERE "); //$NON-NLS-1$
+    sqlSelectForChangeSet = builder.toString();
+  }
+
+  private List<ITypeMapping> createValueMappings(EStructuralFeature[] features)
+  {
+    List<ITypeMapping> mappings = new ArrayList<ITypeMapping>();
+    for (EStructuralFeature feature : features)
+    {
+      if (!feature.isMany())
+      {
+        ITypeMapping mapping = mappingStrategy.createValueMapping(feature);
+        mapping.createDBField(getTable());
+        mappings.add(mapping);
+
+        if (feature.isUnsettable())
+        {
+          String fieldName = mappingStrategy.getUnsettableFieldName(feature);
+          if (unsettableFields == null)
+          {
+            unsettableFields = new LinkedHashMap<EStructuralFeature, String>();
+          }
+
+          unsettableFields.put(feature, fieldName);
+        }
+      }
+    }
+
+    // add unsettable fields to end of table
+    if (unsettableFields != null)
+    {
+      for (String fieldName : unsettableFields.values())
+      {
+        table.addField(fieldName, DBType.BOOLEAN, 1);
+      }
+    }
+
+    return mappings;
+  }
+
+  private List<IListMapping> createListMappings(EStructuralFeature[] features)
+  {
+    List<IListMapping> listMappings = new ArrayList<IListMapping>();
+    for (EStructuralFeature feature : features)
+    {
+      if (feature.isMany())
+      {
+        IListMapping mapping = null;
+        if (FeatureMapUtil.isFeatureMap(feature))
+        {
+          mapping = mappingStrategy.createFeatureMapMapping(eClass, feature);
+        }
+        else
+        {
+          mapping = mappingStrategy.createListMapping(eClass, feature);
+        }
+
+        listMappings.add(mapping);
+
+        // add field for list sizes
+        createListSizeField(feature);
+      }
+    }
+
+    return listMappings;
+  }
+
+  /**
+   * Create an integer field in the attribute tabel for the list size of the associated list mapping.
+   */
+  private void createListSizeField(EStructuralFeature feature)
+  {
+    if (listSizeFields == null)
+    {
+      listSizeFields = new LinkedHashMap<EStructuralFeature, String>();
+    }
+
+    String fieldName = mappingStrategy.getFieldName(feature);
+    table.addField(fieldName, DBType.INTEGER);
+
+    listSizeFields.put(feature, fieldName);
+  }
+
+  /**
+   * Read the revision's values from the DB.
+   * 
+   * @return <code>true</code> if the revision has been read successfully.<br>
+   *         <code>false</code> if the revision does not exist in the DB.
+   */
+  protected final boolean readValuesFromStatement(PreparedStatement stmt, InternalCDORevision revision,
+      IDBStoreAccessor accessor)
+  {
+    ResultSet resultSet = null;
+
+    try
+    {
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Executing Query: {0}", stmt.toString()); //$NON-NLS-1$
+      }
+
+      stmt.setMaxRows(1); // Optimization: only 1 row
+
+      resultSet = stmt.executeQuery();
+      if (!resultSet.next())
+      {
+        if (TRACER.isEnabled())
+        {
+          TRACER.format("Resultset was empty"); //$NON-NLS-1$
+        }
+
+        return false;
+      }
+
+      revision.setVersion(resultSet.getInt(CDODBSchema.ATTRIBUTES_VERSION));
+
+      long timeStamp = resultSet.getLong(CDODBSchema.ATTRIBUTES_CREATED);
+
+      IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+      CDOBranchPoint branchPoint = revision.getBranch().getPoint(timeStamp);
+
+      revision.setBranchPoint(branchPoint);
+      revision.setRevised(resultSet.getLong(CDODBSchema.ATTRIBUTES_REVISED));
+      revision.setResourceID(idHandler.getCDOID(resultSet, CDODBSchema.ATTRIBUTES_RESOURCE));
+      revision.setContainerID(idHandler.getCDOID(resultSet, CDODBSchema.ATTRIBUTES_CONTAINER));
+      revision.setContainingFeatureID(resultSet.getInt(CDODBSchema.ATTRIBUTES_FEATURE));
+
+      for (ITypeMapping mapping : valueMappings)
+      {
+        EStructuralFeature feature = mapping.getFeature();
+        if (feature.isUnsettable())
+        {
+          if (!resultSet.getBoolean(unsettableFields.get(feature)))
+          {
+            // isSet==false -- setValue: null
+            revision.setValue(feature, null);
+            continue;
+          }
+        }
+
+        mapping.readValueToRevision(resultSet, revision);
+      }
+
+      if (listSizeFields != null)
+      {
+        for (Map.Entry<EStructuralFeature, String> listSizeEntry : listSizeFields.entrySet())
+        {
+          EStructuralFeature feature = listSizeEntry.getKey();
+          String fieldName = listSizeEntry.getValue();
+          int size = resultSet.getInt(fieldName);
+
+          // ensure the listSize (TODO: remove assertion)
+          CDOList list = revision.getList(feature, size);
+
+          for (int i = 0; i < size; i++)
+          {
+            list.add(InternalCDOList.UNINITIALIZED);
+          }
+
+          if (list.size() != size)
+          {
+            Assert.isTrue(false);
+          }
+        }
+      }
+
+      return true;
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex);
+    }
+    finally
+    {
+      DBUtil.close(resultSet);
+    }
+  }
+
+  protected final void readLists(IDBStoreAccessor accessor, InternalCDORevision revision, int listChunk)
+  {
+    for (IListMapping listMapping : listMappings)
+    {
+      listMapping.readValues(accessor, revision, listChunk);
+    }
+  }
+
+  protected final IMappingStrategy getMappingStrategy()
+  {
+    return mappingStrategy;
+  }
+
+  public final EClass getEClass()
+  {
+    return eClass;
+  }
+
+  protected final Map<EStructuralFeature, String> getUnsettableFields()
+  {
+    return unsettableFields;
+  }
+
+  protected final Map<EStructuralFeature, String> getListSizeFields()
+  {
+    return listSizeFields;
+  }
+
+  public final List<ITypeMapping> getValueMappings()
+  {
+    return valueMappings;
+  }
+
+  public final ITypeMapping getValueMapping(EStructuralFeature feature)
+  {
+    for (ITypeMapping mapping : valueMappings)
+    {
+      if (mapping.getFeature() == feature)
+      {
+        return mapping;
+      }
+    }
+
+    return null;
+  }
+
+  public final List<IListMapping> getListMappings()
+  {
+    return listMappings;
+  }
+
+  public final IListMapping getListMapping(EStructuralFeature feature)
+  {
+    for (IListMapping mapping : listMappings)
+    {
+      if (mapping.getFeature() == feature)
+      {
+        return mapping;
+      }
+    }
+
+    throw new IllegalArgumentException("List mapping for feature " + feature + " does not exist"); //$NON-NLS-1$ //$NON-NLS-2$
+  }
+
+  protected final IDBTable getTable()
+  {
+    return table;
+  }
+
+  public List<IDBTable> getDBTables()
+  {
+    List<IDBTable> tables = new ArrayList<IDBTable>();
+    tables.add(table);
+
+    for (IListMapping listMapping : listMappings)
+    {
+      tables.addAll(listMapping.getDBTables());
+    }
+
+    return tables;
+  }
+
+  protected void checkDuplicateResources(IDBStoreAccessor accessor, CDORevision revision) throws IllegalStateException
+  {
+    CDOID folderID = (CDOID)revision.data().getContainerID();
+    String name = (String)revision.data().get(EresourcePackage.eINSTANCE.getCDOResourceNode_Name(), 0);
+    CDOID existingID = accessor.readResourceID(folderID, name, revision.getBranch().getHead());
+    if (existingID != null && !existingID.equals(revision.getID()))
+    {
+      throw new IllegalStateException("Duplicate resource or folder: " + name + " in folder " + folderID); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+  }
+
+  protected void writeLists(IDBStoreAccessor accessor, InternalCDORevision revision)
+  {
+    for (IListMapping listMapping : listMappings)
+    {
+      listMapping.writeValues(accessor, revision);
+    }
+  }
+
+  public void writeRevision(IDBStoreAccessor accessor, InternalCDORevision revision, boolean mapType, boolean revise,
+      OMMonitor monitor)
+  {
+    Async async = null;
+    monitor.begin(10);
+
+    try
+    {
+      try
+      {
+        async = monitor.forkAsync();
+        CDOID id = revision.getID();
+        if (mapType)
+        {
+          long timeStamp = revision.getTimeStamp();
+          mappingStrategy.putObjectType(accessor, timeStamp, id, eClass);
+        }
+        else if (revise)
+        {
+          long revised = revision.getTimeStamp() - 1;
+          reviseOldRevision(accessor, id, revision.getBranch(), revised);
+          for (IListMapping mapping : getListMappings())
+          {
+            mapping.objectDetached(accessor, id, revised);
+          }
+        }
+      }
+      finally
+      {
+        if (async != null)
+        {
+          async.stop();
+        }
+      }
+
+      try
+      {
+        async = monitor.forkAsync();
+        if (revision.isResourceFolder() || revision.isResource())
+        {
+          checkDuplicateResources(accessor, revision);
+        }
+      }
+      finally
+      {
+        if (async != null)
+        {
+          async.stop();
+        }
+      }
+
+      try
+      {
+        // Write attribute table always (even without modeled attributes!)
+        async = monitor.forkAsync();
+        writeValues(accessor, revision);
+      }
+      finally
+      {
+        if (async != null)
+        {
+          async.stop();
+        }
+      }
+
+      try
+      {
+        // Write list tables only if they exist
+        if (listMappings != null)
+        {
+          async = monitor.forkAsync(7);
+          writeLists(accessor, revision);
+        }
+        else
+        {
+          monitor.worked(7);
+        }
+      }
+      finally
+      {
+        if (async != null)
+        {
+          async.stop();
+        }
+      }
+    }
+    finally
+    {
+      monitor.done();
+    }
+  }
+
+  public void handleRevisions(IDBStoreAccessor accessor, CDOBranch branch, long timeStamp, boolean exactTime,
+      CDORevisionHandler handler)
+  {
+    // branch parameter is ignored, because either it is null or main branch.
+    // this does not make any difference for non-branching store.
+    // see #handleRevisions() implementation in HorizontalBranchingClassMapping
+    // for branch handling.
+
+    IRepository repository = accessor.getStore().getRepository();
+    CDORevisionManager revisionManager = repository.getRevisionManager();
+    CDOBranchManager branchManager = repository.getBranchManager();
+
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+    ResultSet resultSet = null;
+
+    // TODO: test for timeStamp == INVALID_TIME and encode revision.isValid() as WHERE instead of fetching all revisions
+    // in order to increase performance
+
+    StringBuilder builder = new StringBuilder(sqlSelectForHandle);
+
+    int timeParameters = 0;
+    if (timeStamp != CDOBranchPoint.INVALID_DATE)
+    {
+      if (exactTime)
+      {
+        if (timeStamp != CDOBranchPoint.UNSPECIFIED_DATE)
+        {
+          builder.append(" WHERE "); //$NON-NLS-1$
+          builder.append(CDODBSchema.ATTRIBUTES_CREATED);
+          builder.append("=?"); //$NON-NLS-1$
+          timeParameters = 1;
+        }
+      }
+      else
+      {
+        builder.append(" WHERE "); //$NON-NLS-1$
+        if (timeStamp != CDOBranchPoint.UNSPECIFIED_DATE)
+        {
+          builder.append(CDODBSchema.ATTRIBUTES_CREATED);
+          builder.append(">=?"); //$NON-NLS-1$
+          builder.append(" AND ("); //$NON-NLS-1$
+          builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+          builder.append("<=? OR "); //$NON-NLS-1$
+          builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+          builder.append("="); //$NON-NLS-1$
+          builder.append(CDOBranchPoint.UNSPECIFIED_DATE);
+          builder.append(")"); //$NON-NLS-1$
+          timeParameters = 2;
+        }
+        else
+        {
+          builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+          builder.append("="); //$NON-NLS-1$
+          builder.append(CDOBranchPoint.UNSPECIFIED_DATE);
+        }
+      }
+    }
+
+    try
+    {
+      stmt = statementCache.getPreparedStatement(builder.toString(), ReuseProbability.LOW);
+      for (int i = 0; i < timeParameters; i++)
+      {
+        stmt.setLong(i + 1, timeStamp);
+      }
+
+      resultSet = stmt.executeQuery();
+      while (resultSet.next())
+      {
+        CDOID id = idHandler.getCDOID(resultSet, 1);
+        int version = resultSet.getInt(2);
+
+        if (version >= CDOBranchVersion.FIRST_VERSION)
+        {
+          InternalCDORevision revision = (InternalCDORevision)revisionManager.getRevisionByVersion(id, branchManager
+              .getMainBranch().getVersion(version), CDORevision.UNCHUNKED, true);
+
+          if (!handler.handleRevision(revision))
+          {
+            break;
+          }
+        }
+      }
+    }
+    catch (SQLException e)
+    {
+      throw new DBException(e);
+    }
+    finally
+    {
+      DBUtil.close(resultSet);
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  public Set<CDOID> readChangeSet(IDBStoreAccessor accessor, CDOChangeSetSegment[] segments)
+  {
+    StringBuilder builder = new StringBuilder(sqlSelectForChangeSet);
+    boolean isFirst = true;
+
+    for (int i = 0; i < segments.length; i++)
+    {
+      if (isFirst)
+      {
+        isFirst = false;
+      }
+      else
+      {
+        builder.append(" OR "); //$NON-NLS-1$
+      }
+
+      builder.append(CDODBSchema.ATTRIBUTES_CREATED);
+      builder.append(">=?"); //$NON-NLS-1$
+      builder.append(" AND ("); //$NON-NLS-1$
+      builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+      builder.append("<=? OR "); //$NON-NLS-1$
+      builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+      builder.append("="); //$NON-NLS-1$
+      builder.append(CDOBranchPoint.UNSPECIFIED_DATE);
+      builder.append(")"); //$NON-NLS-1$
+    }
+
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+    ResultSet resultSet = null;
+
+    Set<CDOID> result = new HashSet<CDOID>();
+
+    try
+    {
+      stmt = statementCache.getPreparedStatement(builder.toString(), ReuseProbability.LOW);
+      int column = 1;
+      for (CDOChangeSetSegment segment : segments)
+      {
+        stmt.setLong(column++, segment.getTimeStamp());
+        stmt.setLong(column++, segment.getEndTime());
+      }
+
+      resultSet = stmt.executeQuery();
+      while (resultSet.next())
+      {
+        CDOID id = idHandler.getCDOID(resultSet, 1);
+        result.add(id);
+      }
+
+      return result;
+    }
+    catch (SQLException e)
+    {
+      throw new DBException(e);
+    }
+    finally
+    {
+      DBUtil.close(resultSet);
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  public void detachObject(IDBStoreAccessor accessor, CDOID id, int version, CDOBranch branch, long timeStamp,
+      OMMonitor monitor)
+  {
+    Async async = null;
+    monitor.begin(1 + listMappings.size());
+
+    try
+    {
+      if (version >= CDOBranchVersion.FIRST_VERSION)
+      {
+        reviseOldRevision(accessor, id, branch, timeStamp - 1);
+      }
+
+      detachAttributes(accessor, id, version + 1, branch, timeStamp, monitor.fork());
+
+      // notify list mappings so they can clean up
+      for (IListMapping mapping : getListMappings())
+      {
+        try
+        {
+          async = monitor.forkAsync();
+          mapping.objectDetached(accessor, id, timeStamp);
+        }
+        finally
+        {
+          if (async != null)
+          {
+            async.stop();
+          }
+        }
+      }
+    }
+    finally
+    {
+      monitor.done();
+    }
+  }
+
+  public final boolean queryXRefs(IDBStoreAccessor accessor, QueryXRefsContext context, String idString)
+  {
+    String tableName = getTable().getName();
+    EClass eClass = getEClass();
+    List<EReference> refs = context.getSourceCandidates().get(eClass);
+    List<EReference> scalarRefs = new ArrayList<EReference>();
+
+    for (EReference ref : refs)
+    {
+      if (ref.isMany())
+      {
+        IListMapping listMapping = getListMapping(ref);
+        String where = getListXRefsWhere(context);
+
+        boolean more = listMapping.queryXRefs(accessor, tableName, where, context, idString);
+        if (!more)
+        {
+          return false;
+        }
+      }
+      else
+      {
+        scalarRefs.add(ref);
+      }
+    }
+
+    if (!scalarRefs.isEmpty())
+    {
+      boolean more = queryScalarXRefs(accessor, scalarRefs, context, idString);
+      if (!more)
+      {
+        return false;
+      }
+    }
+
+    return true;
+  }
+
+  protected final boolean queryScalarXRefs(IDBStoreAccessor accessor, List<EReference> scalarRefs,
+      QueryXRefsContext context, String idString)
+  {
+    String tableName = getTable().getName();
+    String where = getListXRefsWhere(context);
+
+    for (EReference ref : scalarRefs)
+    {
+      ITypeMapping valueMapping = getValueMapping(ref);
+      String valueField = valueMapping.getField().getName();
+
+      StringBuilder builder = new StringBuilder();
+      builder.append("SELECT ");
+      builder.append(CDODBSchema.ATTRIBUTES_ID);
+      builder.append(", ");
+      builder.append(valueField);
+      builder.append(" FROM ");
+      builder.append(tableName);
+      builder.append(" WHERE ");
+      builder.append(CDODBSchema.ATTRIBUTES_VERSION);
+      builder.append(">0 AND ");
+      builder.append(where);
+      builder.append(" AND ");
+      builder.append(valueField);
+      builder.append(" IN ");
+      builder.append(idString);
+      String sql = builder.toString();
+
+      IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+      ResultSet resultSet = null;
+      Statement stmt = null;
+
+      try
+      {
+        stmt = accessor.getConnection().createStatement();
+        if (TRACER.isEnabled())
+        {
+          TRACER.format("Query XRefs (attributes): {0}", sql);
+        }
+
+        resultSet = stmt.executeQuery(sql);
+        while (resultSet.next())
+        {
+          CDOID sourceID = idHandler.getCDOID(resultSet, 1);
+          CDOID targetID = idHandler.getCDOID(resultSet, 2);
+
+          boolean more = context.addXRef(targetID, sourceID, ref, 0);
+          if (TRACER.isEnabled())
+          {
+            TRACER.format("  add XRef to context: src={0}, tgt={1}, idx=0", sourceID, targetID);
+          }
+
+          if (!more)
+          {
+            if (TRACER.isEnabled())
+            {
+              TRACER.format("  result limit reached. Ignoring further results.");
+            }
+
+            return false;
+          }
+        }
+      }
+      catch (SQLException ex)
+      {
+        throw new DBException(ex);
+      }
+      finally
+      {
+        DBUtil.close(resultSet);
+        DBUtil.close(stmt);
+      }
+    }
+
+    return true;
+  }
+
+  protected abstract String getListXRefsWhere(QueryXRefsContext context);
+
+  protected abstract void detachAttributes(IDBStoreAccessor accessor, CDOID id, int version, CDOBranch branch,
+      long timeStamp, OMMonitor fork);
+
+  protected abstract void reviseOldRevision(IDBStoreAccessor accessor, CDOID id, CDOBranch branch, long timeStamp);
+
+  protected abstract void writeValues(IDBStoreAccessor accessor, InternalCDORevision revision);
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AbstractHorizontalMappingStrategy.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AbstractHorizontalMappingStrategy.java
new file mode 100644
index 0000000..7a9cd33
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AbstractHorizontalMappingStrategy.java
@@ -0,0 +1,480 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - 271444: [DB] Multiple refactorings bug 271444
+ */
+package org.eclipse.emf.cdo.server.internal.db.mapping.horizontal;
+
+import org.eclipse.emf.cdo.common.CDOCommonRepository.IDGenerationLocation;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.model.CDOClassifierRef;
+import org.eclipse.emf.cdo.common.protocol.CDODataInput;
+import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.eresource.CDOResourceNode;
+import org.eclipse.emf.cdo.eresource.EresourcePackage;
+import org.eclipse.emf.cdo.server.IStoreAccessor.QueryResourcesContext;
+import org.eclipse.emf.cdo.server.IStoreAccessor.QueryXRefsContext;
+import org.eclipse.emf.cdo.server.db.IDBStore;
+import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
+import org.eclipse.emf.cdo.server.db.IIDHandler;
+import org.eclipse.emf.cdo.server.db.mapping.IClassMapping;
+import org.eclipse.emf.cdo.server.db.mapping.IListMapping;
+import org.eclipse.emf.cdo.server.internal.db.CDODBSchema;
+import org.eclipse.emf.cdo.server.internal.db.IObjectTypeMapper;
+import org.eclipse.emf.cdo.server.internal.db.bundle.OM;
+import org.eclipse.emf.cdo.server.internal.db.mapping.AbstractMappingStrategy;
+
+import org.eclipse.net4j.db.DBException;
+import org.eclipse.net4j.db.DBUtil;
+import org.eclipse.net4j.db.IDBAdapter;
+import org.eclipse.net4j.db.ddl.IDBTable;
+import org.eclipse.net4j.util.lifecycle.LifecycleUtil;
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+import org.eclipse.net4j.util.om.trace.ContextTracer;
+
+import org.eclipse.emf.ecore.EClass;
+
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * * This abstract base class refines {@link AbstractMappingStrategy} by implementing aspects common to horizontal
+ * mapping strategies -- namely:
+ * <ul>
+ * <li>object type cache (table cdo_objects)
+ * <li>resource query handling
+ * </ul>
+ * 
+ * @author Eike Stepper
+ * @since 2.0
+ */
+public abstract class AbstractHorizontalMappingStrategy extends AbstractMappingStrategy
+{
+  private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG, AbstractHorizontalMappingStrategy.class);
+
+  /**
+   * The associated object type mapper.
+   */
+  private IObjectTypeMapper objectTypeMapper;
+
+  public CDOClassifierRef readObjectType(IDBStoreAccessor accessor, CDOID id)
+  {
+    return objectTypeMapper.getObjectType(accessor, id);
+  }
+
+  public void putObjectType(IDBStoreAccessor accessor, long timeStamp, CDOID id, EClass type)
+  {
+    objectTypeMapper.putObjectType(accessor, timeStamp, id, type);
+  }
+
+  public void repairAfterCrash(IDBAdapter dbAdapter, Connection connection)
+  {
+    IDBStore store = getStore();
+    if (store.getRepository().getIDGenerationLocation() == IDGenerationLocation.STORE)
+    {
+      IIDHandler idHandler = store.getIDHandler();
+
+      CDOID minLocalID = getMinLocalID(connection);
+      idHandler.setNextLocalObjectID(minLocalID);
+
+      CDOID maxID = objectTypeMapper.getMaxID(connection, idHandler);
+      idHandler.setLastObjectID(maxID);
+    }
+  }
+
+  public void queryResources(IDBStoreAccessor accessor, QueryResourcesContext context)
+  {
+    // only support timestamp in audit mode
+    if (context.getTimeStamp() != CDORevision.UNSPECIFIED_DATE && !hasAuditSupport())
+    {
+      throw new IllegalArgumentException("Mapping Strategy does not support audits"); //$NON-NLS-1$
+    }
+
+    EresourcePackage resourcesPackage = EresourcePackage.eINSTANCE;
+
+    // first query folders
+    IClassMapping resourceFolder = getClassMapping(resourcesPackage.getCDOResourceFolder());
+    boolean shallContinue = queryResources(accessor, resourceFolder, context);
+
+    // not enough results? -> query resources
+    if (shallContinue)
+    {
+      IClassMapping resource = getClassMapping(resourcesPackage.getCDOResource());
+      queryResources(accessor, resource, context);
+    }
+  }
+
+  public void queryXRefs(IDBStoreAccessor accessor, QueryXRefsContext context)
+  {
+    IIDHandler idHandler = getStore().getIDHandler();
+    StringBuilder builder = null;
+
+    // create a string containing "(id1,id2,...)"
+    // NOTE: this might not scale infinitely, because of dbms-dependent
+    // max size for SQL strings. But for now, it's the easiest way...
+    for (CDOID targetID : context.getTargetObjects().keySet())
+    {
+      // NOTE: currently no support for external references!
+      if (builder == null)
+      {
+        builder = new StringBuilder("(");
+      }
+      else
+      {
+        builder.append(",");
+      }
+
+      idHandler.appendCDOID(builder, targetID);
+    }
+
+    builder.append(")");
+    String idString = builder.toString();
+
+    for (EClass eClass : context.getSourceCandidates().keySet())
+    {
+      IClassMapping classMapping = getClassMapping(eClass);
+      boolean more = classMapping.queryXRefs(accessor, context, idString);
+      if (!more)
+      {
+        // cancel query (max results reached or user canceled)
+        return;
+      }
+    }
+  }
+
+  public void rawExport(IDBStoreAccessor accessor, CDODataOutput out, int fromBranchID, int toBranchID,
+      long fromCommitTime, long toCommitTime) throws IOException
+  {
+    StringBuilder builder = new StringBuilder();
+    builder.append(" WHERE a_t."); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_CREATED);
+    builder.append(" BETWEEN "); //$NON-NLS-1$
+    builder.append(fromCommitTime);
+    builder.append(" AND "); //$NON-NLS-1$
+    builder.append(toCommitTime);
+
+    String attrSuffix = builder.toString();
+    Connection connection = accessor.getConnection();
+
+    Collection<IClassMapping> classMappings = getClassMappings(true).values();
+    out.writeInt(classMappings.size());
+
+    for (IClassMapping classMapping : classMappings)
+    {
+      EClass eClass = classMapping.getEClass();
+      out.writeCDOClassifierRef(eClass);
+
+      IDBTable table = classMapping.getDBTables().get(0);
+      DBUtil.serializeTable(out, connection, table, "a_t", attrSuffix);
+
+      for (IListMapping listMapping : classMapping.getListMappings())
+      {
+        rawExportList(out, connection, listMapping, table, attrSuffix);
+      }
+    }
+
+    objectTypeMapper.rawExport(connection, out, fromCommitTime, toCommitTime);
+  }
+
+  protected void rawExportList(CDODataOutput out, Connection connection, IListMapping listMapping, IDBTable attrTable,
+      String attrSuffix) throws IOException
+  {
+    for (IDBTable table : listMapping.getDBTables())
+    {
+      String listSuffix = ", " + attrTable + " a_t" + attrSuffix;
+      String listJoin = getListJoin("a_t", "l_t");
+      if (listJoin != null)
+      {
+        listSuffix += listJoin;
+      }
+
+      DBUtil.serializeTable(out, connection, table, "l_t", listSuffix);
+    }
+  }
+
+  public void rawImport(IDBStoreAccessor accessor, CDODataInput in, long fromCommitTime, long toCommitTime,
+      OMMonitor monitor) throws IOException
+  {
+    int size = in.readInt();
+    if (size == 0)
+    {
+      return;
+    }
+
+    int objectTypeMapperWork = 10;
+    monitor.begin(3 * size + objectTypeMapperWork);
+
+    try
+    {
+      Connection connection = accessor.getConnection();
+      for (int i = 0; i < size; i++)
+      {
+        EClass eClass = (EClass)in.readCDOClassifierRefAndResolve();
+        IClassMapping classMapping = getClassMapping(eClass);
+
+        IDBTable table = classMapping.getDBTables().get(0);
+        DBUtil.deserializeTable(in, connection, table, monitor.fork());
+        rawImportReviseOldRevisions(connection, table, monitor.fork());
+        rawImportUnreviseNewRevisions(connection, table, fromCommitTime, toCommitTime, monitor.fork());
+
+        List<IListMapping> listMappings = classMapping.getListMappings();
+        int listSize = listMappings.size();
+        if (listSize == 0)
+        {
+          monitor.worked();
+        }
+        else
+        {
+          OMMonitor listMonitor = monitor.fork();
+          listMonitor.begin(listSize);
+
+          try
+          {
+            for (IListMapping listMapping : listMappings)
+            {
+              rawImportList(in, connection, listMapping, listMonitor.fork());
+            }
+          }
+          finally
+          {
+            listMonitor.done();
+          }
+        }
+      }
+
+      objectTypeMapper.rawImport(connection, in, monitor.fork(objectTypeMapperWork));
+    }
+    finally
+    {
+      monitor.done();
+    }
+  }
+
+  protected void rawImportUnreviseNewRevisions(Connection connection, IDBTable table, long fromCommitTime,
+      long toCommitTime, OMMonitor monitor)
+  {
+    throw new UnsupportedOperationException("Must be overridden");
+  }
+
+  protected void rawImportReviseOldRevisions(Connection connection, IDBTable table, OMMonitor monitor)
+  {
+    throw new UnsupportedOperationException("Must be overridden");
+  }
+
+  protected void rawImportList(CDODataInput in, Connection connection, IListMapping listMapping, OMMonitor monitor)
+      throws IOException
+  {
+    Collection<IDBTable> tables = listMapping.getDBTables();
+    int size = tables.size();
+    if (size == 0)
+    {
+      return;
+    }
+
+    monitor.begin(size);
+
+    try
+    {
+      for (IDBTable table : tables)
+      {
+        DBUtil.deserializeTable(in, connection, table, monitor.fork());
+      }
+    }
+    finally
+    {
+      monitor.done();
+    }
+  }
+
+  public String getListJoin(String attrTable, String listTable)
+  {
+    return " AND " + attrTable + "." + CDODBSchema.ATTRIBUTES_ID + "=" + listTable + "." + CDODBSchema.LIST_REVISION_ID;
+  }
+
+  @Override
+  protected boolean isMapped(EClass eClass)
+  {
+    return !eClass.isAbstract() && !eClass.isInterface();
+  }
+
+  @Override
+  protected Collection<EClass> getClassesWithObjectInfo()
+  {
+    return getClassMappings().keySet();
+  }
+
+  @Override
+  protected void doActivate() throws Exception
+  {
+    super.doActivate();
+    if (objectTypeMapper == null)
+    {
+      objectTypeMapper = createObjectTypeMapper();
+    }
+
+    LifecycleUtil.activate(objectTypeMapper);
+  }
+
+  @Override
+  protected void doDeactivate() throws Exception
+  {
+    LifecycleUtil.deactivate(objectTypeMapper);
+    super.doDeactivate();
+  }
+
+  private IObjectTypeMapper createObjectTypeMapper()
+  {
+    ObjectTypeTable table = new ObjectTypeTable();
+    table.setMappingStrategy(this);
+
+    int cacheSize = getObjectTypeCacheSize();
+    if (cacheSize == 0)
+    {
+      return table;
+    }
+
+    ObjectTypeCache cache = new ObjectTypeCache(cacheSize);
+    cache.setMappingStrategy(this);
+    cache.setDelegate(table);
+    return cache;
+  }
+
+  private int getObjectTypeCacheSize()
+  {
+    int objectTypeCacheSize = ObjectTypeCache.DEFAULT_CACHE_CAPACITY;
+
+    Object value = getProperties().get(PROP_OBJECT_TYPE_CACHE_SIZE);
+    if (value != null)
+    {
+      try
+      {
+        int intValue = Integer.parseInt((String)value);
+        objectTypeCacheSize = intValue;
+      }
+      catch (NumberFormatException e)
+      {
+        OM.LOG.warn("Malformed configuration option for object type cache size. Using default.");
+      }
+    }
+
+    return objectTypeCacheSize;
+  }
+
+  /**
+   * This is an intermediate implementation. It should be changed after classmappings support a general way to implement
+   * queries ...
+   * 
+   * @param accessor
+   *          the accessor to use.
+   * @param classMapping
+   *          the class mapping of a class instanceof {@link CDOResourceNode} which should be queried.
+   * @param context
+   *          the query context containing the parameters and the result.
+   * @return <code>true</code> if result context is not yet full and query should continue false, if result context is
+   *         full and query should stop.
+   */
+  private boolean queryResources(IDBStoreAccessor accessor, IClassMapping classMapping, QueryResourcesContext context)
+  {
+    IIDHandler idHandler = getStore().getIDHandler();
+    PreparedStatement stmt = null;
+    ResultSet resultSet = null;
+
+    CDOID folderID = context.getFolderID();
+    String name = context.getName();
+    boolean exactMatch = context.exactMatch();
+
+    try
+    {
+      stmt = classMapping.createResourceQueryStatement(accessor, folderID, name, exactMatch, context);
+      resultSet = stmt.executeQuery();
+
+      while (resultSet.next())
+      {
+        CDOID id = idHandler.getCDOID(resultSet, 1);
+        if (TRACER.isEnabled())
+        {
+          TRACER.trace("Resource query returned ID " + id); //$NON-NLS-1$
+        }
+
+        if (!context.addResource(id))
+        {
+          // No more results allowed
+          return false; // don't continue
+        }
+      }
+
+      return true; // continue with other results
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex);
+    }
+    finally
+    {
+      DBUtil.close(resultSet);
+      accessor.getStatementCache().releasePreparedStatement(stmt);
+    }
+  }
+
+  private CDOID getMinLocalID(Connection connection)
+  {
+    IIDHandler idHandler = getStore().getIDHandler();
+    CDOID min = idHandler.getMaxCDOID();
+
+    // Do not call getClassMappings() at this point, as the package registry is not yet initialized!
+    String dbName = getStore().getRepository().getName();
+    List<String> names = DBUtil.getAllTableNames(connection, dbName);
+
+    String prefix = "SELECT MIN(t." + CDODBSchema.ATTRIBUTES_ID + ") FROM " + dbName + "." + CDODBSchema.CDO_OBJECTS
+        + " AS o, " + dbName + ".";
+
+    String suffix = " AS t WHERE t." + CDODBSchema.ATTRIBUTES_BRANCH + "<0 AND t." + CDODBSchema.ATTRIBUTES_ID + "=o."
+        + CDODBSchema.ATTRIBUTES_ID + " AND t." + CDODBSchema.ATTRIBUTES_CREATED + "=o."
+        + CDODBSchema.ATTRIBUTES_CREATED;
+
+    for (String name : names)
+    {
+      Statement stmt = null;
+      ResultSet resultSet = null;
+
+      try
+      {
+        stmt = connection.createStatement();
+        resultSet = stmt.executeQuery(prefix + name + suffix);
+
+        if (resultSet.next())
+        {
+          CDOID id = idHandler.getCDOID(resultSet, 1);
+          if (id != null && idHandler.compare(id, min) < 0)
+          {
+            min = id;
+          }
+        }
+      }
+      catch (SQLException ex)
+      {
+        //$FALL-THROUGH$
+      }
+      finally
+      {
+        DBUtil.close(resultSet);
+        DBUtil.close(stmt);
+      }
+    }
+
+    return min;
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AbstractListTableMapping.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AbstractListTableMapping.java
new file mode 100644
index 0000000..9ca17b9
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AbstractListTableMapping.java
@@ -0,0 +1,485 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - Bug 271444: [DB] Multiple refactorings
+ *    Stefan Winkler - Bug 283998: [DB] Chunk reading for multiple chunks fails
+ *    Stefan Winkler - Bug 329025: [DB] Support branching for range-based mapping strategy
+ */
+package org.eclipse.emf.cdo.server.internal.db.mapping.horizontal;
+
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.revision.CDOList;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.server.IStoreAccessor.QueryXRefsContext;
+import org.eclipse.emf.cdo.server.IStoreChunkReader.Chunk;
+import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
+import org.eclipse.emf.cdo.server.db.IDBStoreChunkReader;
+import org.eclipse.emf.cdo.server.db.IIDHandler;
+import org.eclipse.emf.cdo.server.db.IPreparedStatementCache;
+import org.eclipse.emf.cdo.server.db.IPreparedStatementCache.ReuseProbability;
+import org.eclipse.emf.cdo.server.db.mapping.IMappingStrategy;
+import org.eclipse.emf.cdo.server.db.mapping.ITypeMapping;
+import org.eclipse.emf.cdo.server.internal.db.CDODBSchema;
+import org.eclipse.emf.cdo.server.internal.db.bundle.OM;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+
+import org.eclipse.net4j.db.DBException;
+import org.eclipse.net4j.db.DBType;
+import org.eclipse.net4j.db.DBUtil;
+import org.eclipse.net4j.db.ddl.IDBField;
+import org.eclipse.net4j.db.ddl.IDBIndex.Type;
+import org.eclipse.net4j.db.ddl.IDBTable;
+import org.eclipse.net4j.util.collection.MoveableList;
+import org.eclipse.net4j.util.om.trace.ContextTracer;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * This abstract base class provides basic behavior needed for mapping many-valued attributes to tables.
+ * 
+ * @author Eike Stepper
+ * @since 2.0
+ */
+public abstract class AbstractListTableMapping extends BasicAbstractListTableMapping
+{
+  private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG, AbstractListTableMapping.class);
+
+  /**
+   * The table of this mapping.
+   */
+  private IDBTable table;
+
+  /**
+   * The type mapping for the value field.
+   */
+  private ITypeMapping typeMapping;
+
+  // --------- SQL strings - see initSQLStrings() -----------------
+  private String sqlSelectChunksPrefix;
+
+  private String sqlOrderByIndex;
+
+  private String sqlInsertEntry;
+
+  public AbstractListTableMapping(IMappingStrategy mappingStrategy, EClass eClass, EStructuralFeature feature)
+  {
+    super(mappingStrategy, eClass, feature);
+    initTable();
+    initSQLStrings();
+  }
+
+  private void initTable()
+  {
+    IMappingStrategy mappingStrategy = getMappingStrategy();
+    String tableName = mappingStrategy.getTableName(getContainingClass(), getFeature());
+    table = mappingStrategy.getStore().getDBSchema().addTable(tableName);
+
+    // add fields for keys (cdo_id, version, feature_id)
+    FieldInfo[] fields = getKeyFields();
+    IDBField[] dbFields = new IDBField[fields.length + 1];
+
+    for (int i = 0; i < fields.length; i++)
+    {
+      dbFields[i] = table.addField(fields[i].getName(), fields[i].getDbType());
+    }
+
+    // add field for list index
+    dbFields[dbFields.length - 1] = table.addField(CDODBSchema.LIST_IDX, DBType.INTEGER);
+
+    // add field for value
+    typeMapping = mappingStrategy.createValueMapping(getFeature());
+    typeMapping.createDBField(table, CDODBSchema.LIST_VALUE);
+
+    // add table indexes
+    table.addIndex(Type.UNIQUE, dbFields);
+  }
+
+  protected abstract FieldInfo[] getKeyFields();
+
+  protected abstract void setKeyFields(PreparedStatement stmt, CDORevision revision) throws SQLException;
+
+  public Collection<IDBTable> getDBTables()
+  {
+    return Arrays.asList(table);
+  }
+
+  private void initSQLStrings()
+  {
+    String tableName = getTable().getName();
+    FieldInfo[] fields = getKeyFields();
+
+    // ---------------- SELECT to read chunks ----------------------------
+    StringBuilder builder = new StringBuilder();
+    builder.append("SELECT "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_VALUE);
+    builder.append(" FROM "); //$NON-NLS-1$
+    builder.append(tableName);
+    builder.append(" WHERE "); //$NON-NLS-1$
+
+    for (int i = 0; i < fields.length; i++)
+    {
+      builder.append(fields[i].getName());
+      if (i + 1 < fields.length)
+      {
+        // more to come
+        builder.append("=? AND "); //$NON-NLS-1$
+      }
+      else
+      {
+        // last one
+        builder.append("=? "); //$NON-NLS-1$
+      }
+    }
+
+    sqlSelectChunksPrefix = builder.toString();
+
+    sqlOrderByIndex = " ORDER BY " + CDODBSchema.LIST_IDX; //$NON-NLS-1$
+
+    // ----------------- INSERT - reference entry -----------------
+    builder = new StringBuilder("INSERT INTO "); //$NON-NLS-1$
+    builder.append(tableName);
+    builder.append("("); //$NON-NLS-1$
+
+    for (int i = 0; i < fields.length; i++)
+    {
+      builder.append(fields[i].getName());
+      builder.append(", "); //$NON-NLS-1$
+    }
+
+    builder.append(CDODBSchema.LIST_IDX);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_VALUE);
+    builder.append(") VALUES ("); //$NON-NLS-1$
+    for (int i = 0; i < fields.length; i++)
+    {
+      builder.append("?, "); //$NON-NLS-1$
+    }
+
+    builder.append(" ?, ?)"); //$NON-NLS-1$
+    sqlInsertEntry = builder.toString();
+  }
+
+  protected final IDBTable getTable()
+  {
+    return table;
+  }
+
+  protected final ITypeMapping getTypeMapping()
+  {
+    return typeMapping;
+  }
+
+  public void readValues(IDBStoreAccessor accessor, InternalCDORevision revision, int listChunk)
+  {
+    MoveableList<Object> list = revision.getList(getFeature());
+
+    if (listChunk == 0 || list.size() == 0)
+    {
+      // nothing to read take shortcut
+      return;
+    }
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Reading list values for feature {0}.{1} of {2}v{3}", getContainingClass().getName(), //$NON-NLS-1$
+          getFeature().getName(), revision.getID(), revision.getVersion());
+    }
+
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+    ResultSet resultSet = null;
+
+    try
+    {
+      String sql = sqlSelectChunksPrefix + sqlOrderByIndex;
+      stmt = statementCache.getPreparedStatement(sql, ReuseProbability.HIGH);
+      setKeyFields(stmt, revision);
+
+      if (TRACER.isEnabled())
+      {
+        TRACER.trace(stmt.toString());
+      }
+
+      if (listChunk != CDORevision.UNCHUNKED)
+      {
+        stmt.setMaxRows(listChunk); // optimization - don't read unneeded rows.
+      }
+
+      resultSet = stmt.executeQuery();
+
+      int currentIndex = 0;
+      while ((listChunk == CDORevision.UNCHUNKED || --listChunk >= 0) && resultSet.next())
+      {
+        Object value = typeMapping.readValue(resultSet);
+        if (TRACER.isEnabled())
+        {
+          TRACER.format("Read value for index {0} from result set: {1}", list.size(), value); //$NON-NLS-1$
+        }
+
+        list.set(currentIndex++, value);
+      }
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex);
+    }
+    finally
+    {
+      DBUtil.close(resultSet);
+      statementCache.releasePreparedStatement(stmt);
+    }
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Reading list values done for feature {0}.{1} of {2}v{3}", getContainingClass().getName(), //$NON-NLS-1$
+          getFeature().getName(), revision.getID(), revision.getVersion());
+    }
+  }
+
+  public final void readChunks(IDBStoreChunkReader chunkReader, List<Chunk> chunks, String where)
+  {
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Reading list chunk values for feature {0}.{1} of {2}v{3}", getContainingClass().getName(), //$NON-NLS-1$
+          getFeature().getName(), chunkReader.getRevision().getID(), chunkReader.getRevision().getVersion());
+    }
+
+    IPreparedStatementCache statementCache = chunkReader.getAccessor().getStatementCache();
+    PreparedStatement stmt = null;
+    ResultSet resultSet = null;
+
+    try
+    {
+      StringBuilder builder = new StringBuilder(sqlSelectChunksPrefix);
+      if (where != null)
+      {
+        builder.append(" AND "); //$NON-NLS-1$
+        builder.append(where);
+      }
+
+      builder.append(sqlOrderByIndex);
+
+      String sql = builder.toString();
+      stmt = statementCache.getPreparedStatement(sql, ReuseProbability.LOW);
+      setKeyFields(stmt, chunkReader.getRevision());
+
+      resultSet = stmt.executeQuery();
+
+      Chunk chunk = null;
+      int chunkSize = 0;
+      int chunkIndex = 0;
+      int indexInChunk = 0;
+
+      while (resultSet.next())
+      {
+        Object value = typeMapping.readValue(resultSet);
+
+        if (chunk == null)
+        {
+          chunk = chunks.get(chunkIndex++);
+          chunkSize = chunk.size();
+
+          if (TRACER.isEnabled())
+          {
+            TRACER.format("Current chunk no. {0} is [start = {1}, size = {2}]", chunkIndex - 1, chunk.getStartIndex(), //$NON-NLS-1$
+                chunkSize);
+          }
+        }
+
+        if (TRACER.isEnabled())
+        {
+          TRACER.format("Read value for chunk index {0} from result set: {1}", indexInChunk, value); //$NON-NLS-1$
+        }
+
+        chunk.add(indexInChunk++, value);
+        if (indexInChunk == chunkSize)
+        {
+          if (TRACER.isEnabled())
+          {
+            TRACER.format("Chunk finished"); //$NON-NLS-1$
+          }
+
+          chunk = null;
+          indexInChunk = 0;
+        }
+      }
+
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Reading list chunk values done for feature {0}.{1} of {2}v{3}", getContainingClass().getName(), //$NON-NLS-1$
+            getFeature().getName(), chunkReader.getRevision().getID(), chunkReader.getRevision().getVersion());
+      }
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex);
+    }
+    finally
+    {
+      DBUtil.close(resultSet);
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  public void writeValues(IDBStoreAccessor accessor, InternalCDORevision revision)
+  {
+    CDOList values = revision.getList(getFeature());
+
+    int idx = 0;
+    for (Object element : values)
+    {
+      writeValue(accessor, revision, idx++, element);
+    }
+  }
+
+  protected final void writeValue(IDBStoreAccessor accessor, CDORevision revision, int idx, Object value)
+  {
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Writing value for feature {0}.{1} index {2} of {3}v{4} : {5}", getContainingClass().getName(),
+          getFeature().getName(), idx, revision.getID(), revision.getVersion(), value);
+    }
+
+    try
+    {
+      stmt = statementCache.getPreparedStatement(sqlInsertEntry, ReuseProbability.HIGH);
+
+      setKeyFields(stmt, revision);
+      int column = getKeyFields().length + 1;
+      stmt.setInt(column++, idx);
+      typeMapping.setValue(stmt, column++, value);
+
+      DBUtil.update(stmt, true);
+    }
+    catch (SQLException e)
+    {
+      throw new DBException(e);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  public boolean queryXRefs(IDBStoreAccessor accessor, String mainTableName, String mainTableWhere,
+      QueryXRefsContext context, String idString)
+  {
+    String tableName = getTable().getName();
+    String listJoin = getMappingStrategy().getListJoin("a_t", "l_t");
+
+    StringBuilder builder = new StringBuilder();
+    builder.append("SELECT l_t."); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_ID);
+    builder.append(", l_t."); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_VALUE);
+    builder.append(", l_t."); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_IDX);
+    builder.append(" FROM "); //$NON-NLS-1$
+    builder.append(tableName);
+    builder.append(" AS l_t, ");//$NON-NLS-1$
+    builder.append(mainTableName);
+    builder.append(" AS a_t WHERE ");//$NON-NLS-1$
+    builder.append("a_t." + mainTableWhere);//$NON-NLS-1$
+    builder.append(listJoin);
+    builder.append(" AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_VALUE);
+    builder.append(" IN "); //$NON-NLS-1$
+    builder.append(idString);
+    String sql = builder.toString();
+
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    ResultSet resultSet = null;
+    Statement stmt = null;
+
+    try
+    {
+      stmt = accessor.getConnection().createStatement();
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Query XRefs (list): {0}", sql);
+      }
+
+      resultSet = stmt.executeQuery(sql);
+      while (resultSet.next())
+      {
+        CDOID srcId = idHandler.getCDOID(resultSet, 1);
+        CDOID targetId = idHandler.getCDOID(resultSet, 2);
+        int idx = resultSet.getInt(3);
+
+        boolean more = context.addXRef(targetId, srcId, (EReference)getFeature(), idx);
+        if (TRACER.isEnabled())
+        {
+          TRACER.format("  add XRef to context: src={0}, tgt={1}, idx={2}", srcId, targetId, idx);
+        }
+
+        if (!more)
+        {
+          if (TRACER.isEnabled())
+          {
+            TRACER.format("  result limit reached. Ignoring further results.");
+          }
+
+          return false;
+        }
+      }
+
+      return true;
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex);
+    }
+    finally
+    {
+      DBUtil.close(resultSet);
+      DBUtil.close(stmt);
+    }
+  }
+
+  /**
+   * Used by subclasses to indicate which fields should be in the table. I.e. just a pair of name and DBType ...
+   * 
+   * @author Stefan Winkler
+   */
+  protected static class FieldInfo
+  {
+    private String name;
+
+    private DBType dbType;
+
+    public FieldInfo(String name, DBType dbType)
+    {
+      this.name = name;
+      this.dbType = dbType;
+    }
+
+    public String getName()
+    {
+      return name;
+    }
+
+    public DBType getDbType()
+    {
+      return dbType;
+    }
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AbstractObjectTypeMapper.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AbstractObjectTypeMapper.java
new file mode 100644
index 0000000..d24e223
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AbstractObjectTypeMapper.java
@@ -0,0 +1,69 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - bug 259402
+ *    Stefan Winkler - redesign (prepared statements)
+ *    Stefan Winkler - bug 276926
+ */
+package org.eclipse.emf.cdo.server.internal.db.mapping.horizontal;
+
+import org.eclipse.emf.cdo.server.db.IMetaDataManager;
+import org.eclipse.emf.cdo.server.db.mapping.IMappingStrategy;
+import org.eclipse.emf.cdo.server.internal.db.IObjectTypeMapper;
+
+import org.eclipse.net4j.util.lifecycle.Lifecycle;
+
+/**
+ * @author Eike Stepper
+ * @since 4.0
+ */
+public abstract class AbstractObjectTypeMapper extends Lifecycle implements IObjectTypeMapper
+{
+  private IMappingStrategy mappingStrategy;
+
+  private IMetaDataManager metaDataManager;
+
+  public AbstractObjectTypeMapper()
+  {
+  }
+
+  public IMappingStrategy getMappingStrategy()
+  {
+    return mappingStrategy;
+  }
+
+  public void setMappingStrategy(IMappingStrategy mappingStrategy)
+  {
+    this.mappingStrategy = mappingStrategy;
+  }
+
+  public IMetaDataManager getMetaDataManager()
+  {
+    return metaDataManager;
+  }
+
+  @Override
+  protected void doBeforeActivate() throws Exception
+  {
+    super.doBeforeActivate();
+    checkState(mappingStrategy, "mappingStrategy"); //$NON-NLS-1$
+  }
+
+  @Override
+  protected void doActivate() throws Exception
+  {
+    metaDataManager = getMappingStrategy().getStore().getMetaDataManager();
+  }
+
+  @Override
+  protected void doDeactivate() throws Exception
+  {
+    metaDataManager = null;
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AuditFeatureMapTableMapping.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AuditFeatureMapTableMapping.java
new file mode 100644
index 0000000..a9c7adc
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AuditFeatureMapTableMapping.java
@@ -0,0 +1,68 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others. 
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - 271444: [DB] Multiple refactorings bug 271444
+ *    Christopher Albert - 254455: [DB] Support FeatureMaps bug 254455  
+ */
+package org.eclipse.emf.cdo.server.internal.db.mapping.horizontal;
+
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
+import org.eclipse.emf.cdo.server.db.mapping.IMappingStrategy;
+import org.eclipse.emf.cdo.server.internal.db.CDODBSchema;
+
+import org.eclipse.net4j.db.DBType;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+
+/**
+ * This is a featuremap-table mapping for audit mode. It has ID and version columns and no delta support.
+ * 
+ * @author Eike Stepper
+ * @since 3.0
+ */
+public class AuditFeatureMapTableMapping extends AbstractFeatureMapTableMapping
+{
+  private FieldInfo[] keyFields;
+
+  public AuditFeatureMapTableMapping(IMappingStrategy mappingStrategy, EClass eClass, EStructuralFeature feature)
+  {
+    super(mappingStrategy, eClass, feature);
+  }
+
+  @Override
+  protected FieldInfo[] getKeyFields()
+  {
+    if (keyFields == null)
+    {
+      keyFields = new FieldInfo[] {
+          new FieldInfo(CDODBSchema.FEATUREMAP_REVISION_ID, getMappingStrategy().getStore().getIDHandler().getDBType()),
+          new FieldInfo(CDODBSchema.FEATUREMAP_VERSION, DBType.INTEGER) };
+    }
+
+    return keyFields;
+  }
+
+  @Override
+  protected void setKeyFields(PreparedStatement stmt, CDORevision revision) throws SQLException
+  {
+    getMappingStrategy().getStore().getIDHandler().setCDOID(stmt, 1, revision.getID());
+    stmt.setInt(2, revision.getVersion());
+  }
+
+  public void objectDetached(IDBStoreAccessor accessor, CDOID id, long revised)
+  {
+    // the audit list mapping does not care about revised references -> NOP
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AuditFeatureMapTableMappingWithRanges.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AuditFeatureMapTableMappingWithRanges.java
new file mode 100644
index 0000000..150fc06
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AuditFeatureMapTableMappingWithRanges.java
@@ -0,0 +1,1212 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - Bug 271444: [DB] Multiple refactorings bug 271444
+ *    Christopher Albert - Bug 254455: [DB] Support FeatureMaps bug 254455
+ *    Victor Roldan Betancort - Bug 283998: [DB] Chunk reading for multiple chunks fails
+ *    Lothar Werzinger - Bug 296440: [DB] Change RDB schema to improve scalability of to-many references in audit mode
+ *    Stefan Winkler - cleanup, merge and maintenance
+ *    Stefan Winkler - Bug 285426: [DB] Implement user-defined typeMapping support
+ *    Stefan Winkler - Bug 329025: [DB] Support branching for range-based mapping strategy
+ */
+package org.eclipse.emf.cdo.server.internal.db.mapping.horizontal;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.revision.CDOList;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionUtil;
+import org.eclipse.emf.cdo.common.revision.delta.CDOAddFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOClearFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOContainerFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDeltaVisitor;
+import org.eclipse.emf.cdo.common.revision.delta.CDOListFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOMoveFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDORemoveFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOSetFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOUnsetFeatureDelta;
+import org.eclipse.emf.cdo.server.IRepository;
+import org.eclipse.emf.cdo.server.IStoreAccessor.QueryXRefsContext;
+import org.eclipse.emf.cdo.server.IStoreChunkReader.Chunk;
+import org.eclipse.emf.cdo.server.db.IDBStore;
+import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
+import org.eclipse.emf.cdo.server.db.IDBStoreChunkReader;
+import org.eclipse.emf.cdo.server.db.IIDHandler;
+import org.eclipse.emf.cdo.server.db.IPreparedStatementCache;
+import org.eclipse.emf.cdo.server.db.IPreparedStatementCache.ReuseProbability;
+import org.eclipse.emf.cdo.server.db.mapping.IListMappingDeltaSupport;
+import org.eclipse.emf.cdo.server.db.mapping.IMappingStrategy;
+import org.eclipse.emf.cdo.server.db.mapping.ITypeMapping;
+import org.eclipse.emf.cdo.server.internal.db.CDODBSchema;
+import org.eclipse.emf.cdo.server.internal.db.bundle.OM;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+
+import org.eclipse.net4j.db.DBException;
+import org.eclipse.net4j.db.DBType;
+import org.eclipse.net4j.db.DBUtil;
+import org.eclipse.net4j.db.ddl.IDBField;
+import org.eclipse.net4j.db.ddl.IDBIndex.Type;
+import org.eclipse.net4j.db.ddl.IDBTable;
+import org.eclipse.net4j.util.ImplementationError;
+import org.eclipse.net4j.util.collection.MoveableList;
+import org.eclipse.net4j.util.om.trace.ContextTracer;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.util.FeatureMap;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This is a featuremap-table mapping for audit mode. It is optimized for frequent insert operations at the list's end,
+ * which causes just 1 DB row to be changed. This is achieved by introducing a version range (columns
+ * {@link CDODBSchema#LIST_REVISION_VERSION_ADDED cdo_version_added} and
+ * {@link CDODBSchema#LIST_REVISION_VERSION_REMOVED cdo_version_removed}) which records for which revisions a particular
+ * entry existed. Also, this mapping is mainly optimized for potentially very large lists: the need for having the
+ * complete list stored in memory to do in-the-middle-moved and inserts is traded in for a few more DB access
+ * operations.
+ * 
+ * @author Eike Stepper
+ * @author Stefan Winkler
+ * @author Lothar Werzinger
+ * @since 3.0
+ */
+public class AuditFeatureMapTableMappingWithRanges extends BasicAbstractListTableMapping implements
+    IListMappingDeltaSupport
+{
+  private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG, AuditFeatureMapTableMappingWithRanges.class);
+
+  /**
+   * Used to clean up lists for detached objects.
+   */
+  private static final int FINAL_VERSION = Integer.MAX_VALUE;
+
+  /**
+   * The table of this mapping.
+   */
+  private IDBTable table;
+
+  /**
+   * The tags mapped to column names
+   */
+  private HashMap<CDOID, String> tagMap;
+
+  /**
+   * Column name Set
+   */
+  private List<String> columnNames;
+
+  /**
+   * The type mappings for the value fields.
+   */
+  private Map<CDOID, ITypeMapping> typeMappings;
+
+  private List<DBType> dbTypes;
+
+  // --------- SQL strings - see initSQLStrings() -----------------
+
+  private String sqlSelectChunksPrefix;
+
+  private String sqlOrderByIndex;
+
+  private String sqlInsert;
+
+  private String sqlRemoveEntry;
+
+  private String sqlDeleteEntry;
+
+  private String sqlUpdateIndex;
+
+  private String sqlGetValue;
+
+  private String sqlClearList;
+
+  private String sqlDeleteList;
+
+  public AuditFeatureMapTableMappingWithRanges(IMappingStrategy mappingStrategy, EClass eClass,
+      EStructuralFeature feature)
+  {
+    super(mappingStrategy, eClass, feature);
+    initDBTypes();
+    initTable();
+    initSQLStrings();
+  }
+
+  private void initDBTypes()
+  {
+    // TODO add annotation processing here ...
+    ITypeMapping.Registry registry = ITypeMapping.Registry.INSTANCE;
+    dbTypes = new ArrayList<DBType>(registry.getDefaultFeatureMapDBTypes());
+  }
+
+  private void initTable()
+  {
+    IDBStore store = getMappingStrategy().getStore();
+    String tableName = getMappingStrategy().getTableName(getContainingClass(), getFeature());
+    table = store.getDBSchema().addTable(tableName);
+
+    // add fields for CDOID
+    IDBField idField = table.addField(CDODBSchema.FEATUREMAP_REVISION_ID, store.getIDHandler().getDBType());
+
+    // add fields for version range
+    IDBField versionAddedField = table.addField(CDODBSchema.FEATUREMAP_VERSION_ADDED, DBType.INTEGER);
+    IDBField versionRemovedField = table.addField(CDODBSchema.FEATUREMAP_VERSION_REMOVED, DBType.INTEGER);
+
+    // add field for list index
+    IDBField idxField = table.addField(CDODBSchema.FEATUREMAP_IDX, DBType.INTEGER);
+
+    // add field for FeatureMap tag (MetaID for Feature in CDO registry)
+    IDBField tagField = table.addField(CDODBSchema.FEATUREMAP_TAG, store.getIDHandler().getDBType());
+
+    tagMap = new HashMap<CDOID, String>();
+    typeMappings = new HashMap<CDOID, ITypeMapping>();
+    columnNames = new ArrayList<String>();
+
+    // create columns for all DBTypes
+    for (DBType type : getDBTypes())
+    {
+      String column = CDODBSchema.FEATUREMAP_VALUE + "_" + type.name();
+      table.addField(column, type);
+      columnNames.add(column);
+    }
+
+    // TODO think about indices
+    table.addIndex(Type.NON_UNIQUE, idField);
+    table.addIndex(Type.NON_UNIQUE, versionAddedField);
+    table.addIndex(Type.NON_UNIQUE, versionRemovedField);
+    table.addIndex(Type.NON_UNIQUE, idxField);
+    table.addIndex(Type.NON_UNIQUE, tagField);
+  }
+
+  private void initSQLStrings()
+  {
+    String tableName = getTable().getName();
+
+    // ---------------- SELECT to read chunks ----------------------------
+    StringBuilder builder = new StringBuilder();
+    builder.append("SELECT "); //$NON-NLS-1$
+
+    builder.append(CDODBSchema.FEATUREMAP_TAG);
+    builder.append(", "); //$NON-NLS-1$
+
+    Iterator<String> iter = columnNames.iterator();
+    while (iter.hasNext())
+    {
+      builder.append(iter.next());
+      if (iter.hasNext())
+      {
+        builder.append(", "); //$NON-NLS-1$
+      }
+    }
+
+    builder.append(" FROM "); //$NON-NLS-1$
+    builder.append(tableName);
+    builder.append(" WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_REVISION_ID);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_VERSION_ADDED);
+    builder.append("<=? AND ("); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_VERSION_REMOVED);
+    builder.append(" IS NULL OR "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_VERSION_REMOVED);
+    builder.append(">?)"); //$NON-NLS-1$
+    sqlSelectChunksPrefix = builder.toString();
+
+    sqlOrderByIndex = " ORDER BY " + CDODBSchema.FEATUREMAP_IDX; //$NON-NLS-1$
+
+    // ----------------- INSERT - prefix -----------------
+    builder = new StringBuilder("INSERT INTO "); //$NON-NLS-1$
+    builder.append(tableName);
+    builder.append("("); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_REVISION_ID);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_VERSION_ADDED);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_VERSION_REMOVED);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_IDX);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_TAG);
+
+    for (int i = 0; i < columnNames.size(); i++)
+    {
+      builder.append(", "); //$NON-NLS-1$
+      builder.append(columnNames.get(i));
+    }
+
+    builder.append(") VALUES (?, ?, ?, ?, ?"); //$NON-NLS-1$
+    for (int i = 0; i < columnNames.size(); i++)
+    {
+      builder.append(", ?"); //$NON-NLS-1$
+    }
+
+    builder.append(")"); //$NON-NLS-1$
+    sqlInsert = builder.toString();
+
+    // ----------------- remove current entry -----------------
+    builder = new StringBuilder("UPDATE "); //$NON-NLS-1$
+    builder.append(tableName);
+    builder.append(" SET "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_VERSION_REMOVED);
+    builder.append("=? "); //$NON-NLS-1$
+    builder.append(" WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_REVISION_ID);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_IDX);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_VERSION_REMOVED);
+    builder.append(" IS NULL"); //$NON-NLS-1$
+    sqlRemoveEntry = builder.toString();
+
+    // ----------------- delete temporary entry -----------------
+    builder = new StringBuilder("DELETE FROM "); //$NON-NLS-1$
+    builder.append(tableName);
+    builder.append(" WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_REVISION_ID);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_IDX);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_VERSION_ADDED);
+    builder.append("=?"); //$NON-NLS-1$
+    sqlDeleteEntry = builder.toString();
+
+    // ----------------- update index -----------------
+    builder = new StringBuilder("UPDATE "); //$NON-NLS-1$
+    builder.append(tableName);
+    builder.append(" SET "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_IDX);
+    builder.append("=? WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_REVISION_ID);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_VERSION_ADDED);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_IDX);
+    builder.append("=?"); //$NON-NLS-1$
+    sqlUpdateIndex = builder.toString();
+
+    // ----------------- get current value -----------------
+    builder = new StringBuilder("SELECT "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_TAG);
+    builder.append(", "); //$NON-NLS-1$
+
+    iter = columnNames.iterator();
+    while (iter.hasNext())
+    {
+      builder.append(iter.next());
+      if (iter.hasNext())
+      {
+        builder.append(", "); //$NON-NLS-1$
+      }
+    }
+
+    builder.append(" FROM "); //$NON-NLS-1$
+    builder.append(tableName);
+    builder.append(" WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_REVISION_ID);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_IDX);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_VERSION_REMOVED);
+    builder.append(" IS NULL"); //$NON-NLS-1$
+    sqlGetValue = builder.toString();
+
+    // ----------- clear list items -------------------------
+    builder = new StringBuilder("UPDATE "); //$NON-NLS-1$
+    builder.append(tableName);
+    builder.append(" SET "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_VERSION_REMOVED);
+    builder.append("=? "); //$NON-NLS-1$
+    builder.append(" WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_REVISION_ID);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_VERSION_REMOVED);
+    builder.append(" IS NULL"); //$NON-NLS-1$
+    sqlClearList = builder.toString();
+
+    // ----------- delete temporary list items -------------------------
+    builder = new StringBuilder("DELETE FROM "); //$NON-NLS-1$
+    builder.append(tableName);
+    builder.append(" WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_REVISION_ID);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_VERSION_ADDED);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_VERSION_REMOVED);
+    builder.append(" IS NULL"); //$NON-NLS-1$
+    sqlDeleteList = builder.toString();
+  }
+
+  protected List<DBType> getDBTypes()
+  {
+    return dbTypes;
+  }
+
+  public Collection<IDBTable> getDBTables()
+  {
+    return Arrays.asList(table);
+  }
+
+  protected final IDBTable getTable()
+  {
+    return table;
+  }
+
+  protected final List<String> getColumnNames()
+  {
+    return columnNames;
+  }
+
+  protected final Map<CDOID, ITypeMapping> getTypeMappings()
+  {
+    return typeMappings;
+  }
+
+  protected final Map<CDOID, String> getTagMap()
+  {
+    return tagMap;
+  }
+
+  public void readValues(IDBStoreAccessor accessor, InternalCDORevision revision, int listChunk)
+  {
+    MoveableList<Object> list = revision.getList(getFeature());
+
+    if (listChunk == 0 || list.size() == 0)
+    {
+      // nothing to read take shortcut
+      return;
+    }
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Reading list values for feature {0}.{1} of {2}v{3}", getContainingClass().getName(), getFeature() //$NON-NLS-1$
+          .getName(), revision.getID(), revision.getVersion());
+    }
+
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+    ResultSet resultSet = null;
+
+    try
+    {
+      String sql = sqlSelectChunksPrefix + sqlOrderByIndex;
+
+      stmt = statementCache.getPreparedStatement(sql, ReuseProbability.HIGH);
+
+      idHandler.setCDOID(stmt, 1, revision.getID());
+      stmt.setInt(2, revision.getVersion());
+      stmt.setInt(3, revision.getVersion());
+
+      if (listChunk != CDORevision.UNCHUNKED)
+      {
+        stmt.setMaxRows(listChunk); // optimization - don't read unneeded rows.
+      }
+
+      resultSet = stmt.executeQuery();
+
+      int currentIndex = 0;
+      while ((listChunk == CDORevision.UNCHUNKED || --listChunk >= 0) && resultSet.next())
+      {
+        CDOID tag = idHandler.getCDOID(resultSet, 1);
+        Object value = getTypeMapping(tag).readValue(resultSet);
+
+        if (TRACER.isEnabled())
+        {
+          TRACER.format("Read value for index {0} from result set: {1}", list.size(), value); //$NON-NLS-1$
+        }
+
+        list.set(currentIndex++, CDORevisionUtil.createFeatureMapEntry(getFeatureByTag(tag), value));
+      }
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex);
+    }
+    finally
+    {
+      DBUtil.close(resultSet);
+      statementCache.releasePreparedStatement(stmt);
+    }
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Reading list values done for feature {0}.{1} of {2}v{3}", getContainingClass().getName(), //$NON-NLS-1$
+          getFeature().getName(), revision.getID(), revision.getVersion());
+    }
+  }
+
+  private void addFeature(CDOID tag)
+  {
+    EStructuralFeature modelFeature = getFeatureByTag(tag);
+
+    ITypeMapping typeMapping = getMappingStrategy().createValueMapping(modelFeature);
+    String column = CDODBSchema.FEATUREMAP_VALUE + "_" + typeMapping.getDBType(); //$NON-NLS-1$
+
+    tagMap.put(tag, column);
+    typeMapping.setDBField(table, column);
+    typeMappings.put(tag, typeMapping);
+  }
+
+  public final void readChunks(IDBStoreChunkReader chunkReader, List<Chunk> chunks, String where)
+  {
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Reading list chunk values for feature {0}.{1} of {2}v{3}", getContainingClass().getName(), //$NON-NLS-1$
+          getFeature().getName(), chunkReader.getRevision().getID(), chunkReader.getRevision().getVersion());
+    }
+
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = chunkReader.getAccessor().getStatementCache();
+    PreparedStatement stmt = null;
+    ResultSet resultSet = null;
+
+    try
+    {
+      StringBuilder builder = new StringBuilder(sqlSelectChunksPrefix);
+      if (where != null)
+      {
+        builder.append(" AND "); //$NON-NLS-1$
+        builder.append(where);
+      }
+
+      builder.append(sqlOrderByIndex);
+
+      String sql = builder.toString();
+      stmt = statementCache.getPreparedStatement(sql, ReuseProbability.LOW);
+      idHandler.setCDOID(stmt, 1, chunkReader.getRevision().getID());
+      stmt.setInt(2, chunkReader.getRevision().getVersion());
+      stmt.setInt(3, chunkReader.getRevision().getVersion());
+
+      resultSet = stmt.executeQuery();
+
+      Chunk chunk = null;
+      int chunkSize = 0;
+      int chunkIndex = 0;
+      int indexInChunk = 0;
+
+      while (resultSet.next())
+      {
+        CDOID tag = idHandler.getCDOID(resultSet, 1);
+        Object value = getTypeMapping(tag).readValue(resultSet);
+
+        if (chunk == null)
+        {
+          chunk = chunks.get(chunkIndex++);
+          chunkSize = chunk.size();
+
+          if (TRACER.isEnabled())
+          {
+            TRACER.format("Current chunk no. {0} is [start = {1}, size = {2}]", chunkIndex - 1, chunk.getStartIndex(), //$NON-NLS-1$
+                chunkSize);
+          }
+        }
+
+        if (TRACER.isEnabled())
+        {
+          TRACER.format("Read value for chunk index {0} from result set: {1}", indexInChunk, value); //$NON-NLS-1$
+        }
+
+        chunk.add(indexInChunk++, CDORevisionUtil.createFeatureMapEntry(getFeatureByTag(tag), value));
+        if (indexInChunk == chunkSize)
+        {
+          if (TRACER.isEnabled())
+          {
+            TRACER.format("Chunk finished"); //$NON-NLS-1$
+          }
+
+          chunk = null;
+          indexInChunk = 0;
+        }
+      }
+
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Reading list chunk values done for feature {0}.{1} of {2}", getContainingClass().getName(), //$NON-NLS-1$
+            getFeature(), chunkReader.getRevision());
+      }
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex);
+    }
+    finally
+    {
+      DBUtil.close(resultSet);
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  public void writeValues(IDBStoreAccessor accessor, InternalCDORevision revision)
+  {
+    CDOList values = revision.getList(getFeature());
+
+    int idx = 0;
+    for (Object element : values)
+    {
+      writeValue(accessor, revision, idx++, element);
+    }
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Writing done"); //$NON-NLS-1$
+    }
+  }
+
+  protected final void writeValue(IDBStoreAccessor accessor, CDORevision revision, int idx, Object value)
+  {
+    if (TRACER.isEnabled())
+    {
+      TRACER
+          .format(
+              "Writing value for feature {0}.{1} index {2} of {3} : {4}", getContainingClass().getName(), getFeature(), idx, revision, value); //$NON-NLS-1$
+    }
+
+    addEntry(accessor, revision.getID(), revision.getVersion(), idx, value, revision.getTimeStamp());
+  }
+
+  /**
+   * Get column name (lazy).
+   * 
+   * @param tag
+   *          The feature's MetaID in CDO
+   * @return the column name where the values are stored
+   */
+  protected String getColumnName(CDOID tag)
+  {
+    String column = tagMap.get(tag);
+    if (column == null)
+    {
+      addFeature(tag);
+      column = tagMap.get(tag);
+    }
+
+    return column;
+  }
+
+  /**
+   * Get type mapping (lazy).
+   * 
+   * @param tag
+   *          The feature's MetaID in CDO
+   * @return the corresponding type mapping
+   */
+  protected ITypeMapping getTypeMapping(CDOID tag)
+  {
+    ITypeMapping typeMapping = typeMappings.get(tag);
+    if (typeMapping == null)
+    {
+      addFeature(tag);
+      typeMapping = typeMappings.get(tag);
+    }
+
+    return typeMapping;
+  }
+
+  /**
+   * @param metaID
+   * @return the column name where the values are stored
+   */
+  private EStructuralFeature getFeatureByTag(CDOID tag)
+  {
+    return (EStructuralFeature)getMappingStrategy().getStore().getMetaDataManager().getMetaInstance(tag);
+  }
+
+  /**
+   * @param feature
+   *          The EStructuralFeature
+   * @return The feature's MetaID in CDO
+   */
+  protected CDOID getTagByFeature(EStructuralFeature feature, long timestamp)
+  {
+    return getMappingStrategy().getStore().getMetaDataManager().getMetaID(feature, timestamp);
+  }
+
+  /**
+   * Clear a list of a given revision.
+   * 
+   * @param accessor
+   *          the accessor to use
+   * @param id
+   *          the id of the revision from which to remove all items
+   */
+  public void clearList(IDBStoreAccessor accessor, CDOID id, int oldVersion, int newVersion)
+  {
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmtDeleteTemp = null;
+    PreparedStatement stmtClear = null;
+
+    try
+    {
+      // delete temporary entries
+      stmtDeleteTemp = statementCache.getPreparedStatement(sqlDeleteList, ReuseProbability.HIGH);
+      idHandler.setCDOID(stmtDeleteTemp, 1, id);
+      stmtDeleteTemp.setInt(2, newVersion);
+
+      int result = DBUtil.update(stmtDeleteTemp, false);
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("DeleteList result: {0}", result); //$NON-NLS-1$
+      }
+
+      // clear rest of the list
+      stmtClear = statementCache.getPreparedStatement(sqlClearList, ReuseProbability.HIGH);
+      stmtClear.setInt(1, newVersion);
+      idHandler.setCDOID(stmtClear, 2, id);
+
+      result = DBUtil.update(stmtClear, false);
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("ClearList result: {0}", result); //$NON-NLS-1$
+      }
+    }
+    catch (SQLException e)
+    {
+      throw new DBException(e);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmtDeleteTemp);
+      statementCache.releasePreparedStatement(stmtClear);
+    }
+  }
+
+  public void objectDetached(IDBStoreAccessor accessor, CDOID id, long revised)
+  {
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("objectRevised {0}: {1}", id, revised); //$NON-NLS-1$
+    }
+
+    CDOBranch main = getMappingStrategy().getStore().getRepository().getBranchManager().getMainBranch();
+
+    // get revision from cache to find out version number
+    CDORevision revision = getMappingStrategy().getStore().getRepository().getRevisionManager()
+        .getRevision(id, main.getHead(), /* chunksize = */0, CDORevision.DEPTH_NONE, true);
+
+    // set cdo_revision_removed for all list items (so we have no NULL values)
+    clearList(accessor, id, revision.getVersion(), FINAL_VERSION);
+  }
+
+  public void processDelta(final IDBStoreAccessor accessor, final CDOID id, final int branchId, int oldVersion,
+      final int newVersion, long created, CDOListFeatureDelta delta)
+  {
+    IRepository repo = accessor.getStore().getRepository();
+    InternalCDORevision originalRevision = (InternalCDORevision)repo.getRevisionManager().getRevision(id,
+        repo.getBranchManager().getMainBranch().getHead(), /* chunksize = */0, CDORevision.DEPTH_NONE, true);
+
+    int oldListSize = originalRevision.getList(getFeature()).size();
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("ListTableMapping.processDelta for revision {0} - previous list size: {1}", originalRevision, //$NON-NLS-1$
+          oldListSize);
+    }
+
+    // let the visitor collect the changes
+    ListDeltaVisitor visitor = new ListDeltaVisitor(accessor, originalRevision, oldVersion, newVersion, created);
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Processing deltas..."); //$NON-NLS-1$
+    }
+
+    for (CDOFeatureDelta listDelta : delta.getListChanges())
+    {
+      listDelta.accept(visitor);
+    }
+  }
+
+  private class ListDeltaVisitor implements CDOFeatureDeltaVisitor
+  {
+    private IDBStoreAccessor accessor;
+
+    private InternalCDORevision originalRevision;
+
+    private CDOID id;
+
+    private int oldVersion;
+
+    private int newVersion;
+
+    private int lastIndex;
+
+    private long timestamp;
+
+    public ListDeltaVisitor(IDBStoreAccessor accessor, InternalCDORevision originalRevision, int oldVersion,
+        int newVersion, long timestamp)
+    {
+      this.accessor = accessor;
+      this.originalRevision = originalRevision;
+      id = this.originalRevision.getID();
+      this.oldVersion = oldVersion;
+      this.newVersion = newVersion;
+      lastIndex = originalRevision.getList(getFeature()).size() - 1;
+      this.timestamp = timestamp;
+    }
+
+    public void visit(CDOMoveFeatureDelta delta)
+    {
+      int fromIdx = delta.getOldPosition();
+      int toIdx = delta.getNewPosition();
+
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Delta Moving: {0} to {1}", fromIdx, toIdx); //$NON-NLS-1$
+      }
+
+      Object value = getValue(accessor, id, fromIdx);
+
+      // remove the item
+      removeEntry(accessor, id, oldVersion, newVersion, fromIdx);
+
+      // adjust indexes and shift either up or down
+      if (fromIdx < toIdx)
+      {
+        moveOneUp(accessor, id, oldVersion, newVersion, fromIdx + 1, toIdx);
+      }
+      else
+      { // fromIdx > toIdx here
+        moveOneDown(accessor, id, oldVersion, newVersion, toIdx, fromIdx - 1);
+      }
+
+      // create the item
+      addEntry(accessor, id, newVersion, toIdx, value, timestamp);
+    }
+
+    public void visit(CDOAddFeatureDelta delta)
+    {
+      int startIndex = delta.getIndex();
+      int endIndex = lastIndex;
+
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Delta Adding at: {0}", startIndex); //$NON-NLS-1$
+      }
+
+      if (startIndex <= endIndex)
+      {
+        // make room for the new item
+        moveOneDown(accessor, id, oldVersion, newVersion, startIndex, endIndex);
+      }
+
+      // create the item
+      addEntry(accessor, id, newVersion, startIndex, delta.getValue(), timestamp);
+
+      ++lastIndex;
+    }
+
+    public void visit(CDORemoveFeatureDelta delta)
+    {
+      int startIndex = delta.getIndex();
+      int endIndex = lastIndex;
+
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Delta Removing at: {0}", startIndex); //$NON-NLS-1$
+      }
+
+      // remove the item
+      removeEntry(accessor, id, oldVersion, newVersion, startIndex);
+
+      // make room for the new item
+      moveOneUp(accessor, id, oldVersion, newVersion, startIndex + 1, endIndex);
+
+      --lastIndex;
+    }
+
+    public void visit(CDOSetFeatureDelta delta)
+    {
+      int index = delta.getIndex();
+
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Delta Setting at: {0}", index); //$NON-NLS-1$
+      }
+
+      // remove the item
+      removeEntry(accessor, id, oldVersion, newVersion, index);
+
+      // create the item
+      addEntry(accessor, id, newVersion, index, delta.getValue(), timestamp);
+    }
+
+    public void visit(CDOUnsetFeatureDelta delta)
+    {
+      if (delta.getFeature().isUnsettable())
+      {
+        throw new ImplementationError("Should not be called"); //$NON-NLS-1$
+      }
+
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Delta Unsetting"); //$NON-NLS-1$
+      }
+
+      clearList(accessor, id, oldVersion, newVersion);
+      lastIndex = -1;
+    }
+
+    public void visit(CDOListFeatureDelta delta)
+    {
+      throw new ImplementationError("Should not be called"); //$NON-NLS-1$
+    }
+
+    public void visit(CDOClearFeatureDelta delta)
+    {
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Delta Clearing"); //$NON-NLS-1$
+      }
+
+      clearList(accessor, id, oldVersion, newVersion);
+      lastIndex = -1;
+    }
+
+    public void visit(CDOContainerFeatureDelta delta)
+    {
+      throw new ImplementationError("Should not be called"); //$NON-NLS-1$
+    }
+
+    private void moveOneUp(IDBStoreAccessor accessor, CDOID id, int oldVersion, int newVersion, int startIndex,
+        int endIndex)
+    {
+      IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+      IPreparedStatementCache statementCache = accessor.getStatementCache();
+      PreparedStatement stmt = null;
+
+      try
+      {
+        stmt = statementCache.getPreparedStatement(sqlUpdateIndex, ReuseProbability.HIGH);
+
+        for (int index = startIndex; index <= endIndex; ++index)
+        {
+          if (TRACER.isEnabled())
+          {
+            TRACER.format("moveOneUp moving: {0} -> {1}", index, index - 1); //$NON-NLS-1$
+          }
+
+          int column = 1;
+          stmt.setInt(column++, index - 1);
+          idHandler.setCDOID(stmt, column++, id);
+          stmt.setInt(column++, newVersion);
+          stmt.setInt(column++, index);
+
+          int result = DBUtil.update(stmt, false);
+          switch (result)
+          {
+          case 0:
+            Object value = getValue(accessor, id, index);
+            if (TRACER.isEnabled())
+            {
+              TRACER.format("moveOneUp remove: {0}", index); //$NON-NLS-1$
+            }
+
+            removeEntry(accessor, id, oldVersion, newVersion, index);
+            if (TRACER.isEnabled())
+            {
+              TRACER.format("moveOneUp add: {0}", index - 1); //$NON-NLS-1$
+            }
+
+            addEntry(accessor, id, newVersion, index - 1, value, timestamp);
+            break;
+
+          case 1:
+            if (TRACER.isEnabled())
+            {
+              TRACER.format("moveOneUp updated: {0} -> {1}", index, index - 1); //$NON-NLS-1$
+            }
+
+            break;
+
+          default:
+            if (TRACER.isEnabled())
+            {
+              TRACER.format("moveOneUp Too many results: {0} -> {1}: {2}", index, index + 1, result); //$NON-NLS-1$
+            }
+
+            throw new DBException("Too many results"); //$NON-NLS-1$
+          }
+        }
+      }
+      catch (SQLException e)
+      {
+        throw new DBException(e);
+      }
+      finally
+      {
+        statementCache.releasePreparedStatement(stmt);
+      }
+    }
+
+    private void moveOneDown(IDBStoreAccessor accessor, CDOID id, int oldVersion, int newVersion, int startIndex,
+        int endIndex)
+    {
+      IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+      IPreparedStatementCache statementCache = accessor.getStatementCache();
+      PreparedStatement stmt = null;
+
+      try
+      {
+        stmt = statementCache.getPreparedStatement(sqlUpdateIndex, ReuseProbability.HIGH);
+        for (int index = endIndex; index >= startIndex; --index)
+        {
+          if (TRACER.isEnabled())
+          {
+            TRACER.format("moveOneDown moving: {0} -> {1}", index, index + 1); //$NON-NLS-1$
+          }
+
+          int column = 1;
+          stmt.setInt(column++, index + 1);
+          idHandler.setCDOID(stmt, column++, id);
+          stmt.setInt(column++, newVersion);
+          stmt.setInt(column++, index);
+
+          int result = DBUtil.update(stmt, false);
+          switch (result)
+          {
+          case 0:
+            Object value = getValue(accessor, id, index);
+            if (TRACER.isEnabled())
+            {
+              TRACER.format("moveOneDown remove: {0}", index); //$NON-NLS-1$
+            }
+
+            removeEntry(accessor, id, oldVersion, newVersion, index);
+            if (TRACER.isEnabled())
+            {
+              TRACER.format("moveOneDown add: {0}", index + 1); //$NON-NLS-1$
+            }
+
+            addEntry(accessor, id, newVersion, index + 1, value, timestamp);
+            break;
+
+          case 1:
+            if (TRACER.isEnabled())
+            {
+              TRACER.format("moveOneDown updated: {0} -> {1}", index, index + 1); //$NON-NLS-1$
+            }
+
+            break;
+
+          default:
+            if (TRACER.isEnabled())
+            {
+              TRACER.format("moveOneDown Too many results: {0} -> {1}: {2}", index, index + 1, result); //$NON-NLS-1$
+            }
+
+            throw new DBException("Too many results"); //$NON-NLS-1$
+          }
+        }
+      }
+      catch (SQLException e)
+      {
+        throw new DBException(e);
+      }
+      finally
+      {
+        statementCache.releasePreparedStatement(stmt);
+      }
+    }
+  }
+
+  private void addEntry(IDBStoreAccessor accessor, CDOID id, int version, int index, Object value, long timestamp)
+  {
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Adding value for feature() {0}.{1} index {2} of {3}v{4} : {5}", //$NON-NLS-1$
+          getContainingClass().getName(), getFeature().getName(), index, id, version, value);
+    }
+
+    try
+    {
+      FeatureMap.Entry entry = (FeatureMap.Entry)value;
+      EStructuralFeature entryFeature = entry.getEStructuralFeature();
+      CDOID tag = getTagByFeature(entryFeature, timestamp);
+      String columnName = getColumnName(tag);
+
+      stmt = statementCache.getPreparedStatement(sqlInsert, ReuseProbability.HIGH);
+
+      int column = 1;
+      idHandler.setCDOID(stmt, column++, id);
+      stmt.setInt(column++, version);
+      stmt.setNull(column++, DBType.INTEGER.getCode()); // versionRemoved
+      stmt.setInt(column++, index);
+      idHandler.setCDOID(stmt, column++, tag);
+
+      for (int i = 0; i < columnNames.size(); i++)
+      {
+        if (columnNames.get(i).equals(columnName))
+        {
+          getTypeMapping(tag).setValue(stmt, column++, entry.getValue());
+        }
+        else
+        {
+          stmt.setNull(column++, getDBTypes().get(i).getCode());
+        }
+      }
+
+      DBUtil.update(stmt, true);
+    }
+    catch (SQLException e)
+    {
+      throw new DBException(e);
+    }
+    catch (IllegalStateException e)
+    {
+      throw new DBException(e);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  private void removeEntry(IDBStoreAccessor accessor, CDOID id, int oldVersion, int newVersion, int index)
+  {
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Removing value for feature() {0}.{1} index {2} of {3}v{4}", //$NON-NLS-1$
+          getContainingClass().getName(), getFeature().getName(), index, id, newVersion);
+    }
+
+    try
+    {
+      // try to delete a temporary entry first
+      stmt = statementCache.getPreparedStatement(sqlDeleteEntry, ReuseProbability.HIGH);
+
+      int column = 1;
+      idHandler.setCDOID(stmt, column++, id);
+      stmt.setInt(column++, index);
+      stmt.setInt(column++, newVersion);
+
+      int result = DBUtil.update(stmt, false);
+      if (result == 1)
+      {
+        if (TRACER.isEnabled())
+        {
+          TRACER.format("removeEntry deleted: {0}", index); //$NON-NLS-1$
+        }
+      }
+      else if (result > 1)
+      {
+        if (TRACER.isEnabled())
+        {
+          TRACER.format("removeEntry Too many results: {0}: {1}", index, result); //$NON-NLS-1$
+        }
+
+        throw new DBException("Too many results"); //$NON-NLS-1$
+      }
+      else
+      {
+        // no temporary entry found, so mark the entry as removed
+        statementCache.releasePreparedStatement(stmt);
+        stmt = statementCache.getPreparedStatement(sqlRemoveEntry, ReuseProbability.HIGH);
+
+        column = 1;
+        stmt.setInt(column++, newVersion);
+        idHandler.setCDOID(stmt, column++, id);
+        stmt.setInt(column++, index);
+        DBUtil.update(stmt, true);
+      }
+    }
+    catch (SQLException e)
+    {
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Removing value for feature() {0}.{1} index {2} of {3}v{4} FAILED {5}", //$NON-NLS-1$
+            getContainingClass().getName(), getFeature().getName(), index, id, newVersion, e.getMessage());
+      }
+
+      throw new DBException(e);
+    }
+    catch (IllegalStateException e)
+    {
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Removing value for feature() {0}.{1} index {2} of {3}v{4} FAILED {5}", //$NON-NLS-1$
+            getContainingClass().getName(), getFeature().getName(), index, id, newVersion, e.getMessage());
+      }
+
+      throw new DBException(e);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  private FeatureMap.Entry getValue(IDBStoreAccessor accessor, CDOID id, int index)
+  {
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+    FeatureMap.Entry result = null;
+
+    try
+    {
+      stmt = statementCache.getPreparedStatement(sqlGetValue, ReuseProbability.HIGH);
+
+      int column = 1;
+      idHandler.setCDOID(stmt, column++, id);
+      stmt.setInt(column++, index);
+
+      ResultSet resultSet = stmt.executeQuery();
+      if (!resultSet.next())
+      {
+        throw new DBException("getValue expects exactly one result");
+      }
+
+      CDOID tag = idHandler.getCDOID(resultSet, 1);
+      Object value = getTypeMapping(tag).readValue(resultSet);
+      result = CDORevisionUtil.createFeatureMapEntry(getFeatureByTag(tag), value);
+
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Read value (index {0}) from result set: {1}", index, result); //$NON-NLS-1$
+      }
+    }
+    catch (SQLException e)
+    {
+      throw new DBException(e);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+
+    return result;
+  }
+
+  public final boolean queryXRefs(IDBStoreAccessor accessor, String mainTableName, String mainTableWhere,
+      QueryXRefsContext context, String idString)
+  {
+    // must never be called (a feature map is not associated with an EReference feature, so XRefs are nor supported
+    // here)
+    throw new ImplementationError("Should never be called!");
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AuditListTableMapping.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AuditListTableMapping.java
new file mode 100644
index 0000000..9918525
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AuditListTableMapping.java
@@ -0,0 +1,67 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others. 
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - 271444: [DB] Multiple refactorings bug 271444  
+ */
+package org.eclipse.emf.cdo.server.internal.db.mapping.horizontal;
+
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
+import org.eclipse.emf.cdo.server.db.mapping.IMappingStrategy;
+import org.eclipse.emf.cdo.server.internal.db.CDODBSchema;
+
+import org.eclipse.net4j.db.DBType;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+
+/**
+ * This is a list-table mapping for audit mode. It has ID and version columns and no delta support.
+ * 
+ * @author Eike Stepper
+ * @since 2.0
+ */
+public class AuditListTableMapping extends AbstractListTableMapping
+{
+  private FieldInfo[] keyFields;
+
+  public AuditListTableMapping(IMappingStrategy mappingStrategy, EClass eClass, EStructuralFeature feature)
+  {
+    super(mappingStrategy, eClass, feature);
+  }
+
+  @Override
+  protected FieldInfo[] getKeyFields()
+  {
+    if (keyFields == null)
+    {
+      keyFields = new FieldInfo[] {
+          new FieldInfo(CDODBSchema.LIST_REVISION_ID, getMappingStrategy().getStore().getIDHandler().getDBType()),
+          new FieldInfo(CDODBSchema.LIST_REVISION_VERSION, DBType.INTEGER) };
+    }
+
+    return keyFields;
+  }
+
+  @Override
+  protected void setKeyFields(PreparedStatement stmt, CDORevision revision) throws SQLException
+  {
+    getMappingStrategy().getStore().getIDHandler().setCDOID(stmt, 1, revision.getID());
+    stmt.setInt(2, revision.getVersion());
+  }
+
+  public void objectDetached(IDBStoreAccessor accessor, CDOID id, long revised)
+  {
+    // the audit list mapping does not care about revised references -> NOP
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AuditListTableMappingWithRanges.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AuditListTableMappingWithRanges.java
new file mode 100644
index 0000000..a3f0b83
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/AuditListTableMappingWithRanges.java
@@ -0,0 +1,1084 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This class has been derived from AbstractListTableMapping
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Lothar Werzinger - Bug 296440: [DB] Change RDB schema to improve scalability of to-many references in audit mode
+ *    Stefan Winkler - cleanup, merge and maintenance
+ *    Stefan Winkler - Bug 329025: [DB] Support branching for range-based mapping strategy
+ */
+package org.eclipse.emf.cdo.server.internal.db.mapping.horizontal;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.revision.CDOList;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.delta.CDOAddFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOClearFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOContainerFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDeltaVisitor;
+import org.eclipse.emf.cdo.common.revision.delta.CDOListFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOMoveFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDORemoveFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOSetFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOUnsetFeatureDelta;
+import org.eclipse.emf.cdo.server.IRepository;
+import org.eclipse.emf.cdo.server.IStoreAccessor.QueryXRefsContext;
+import org.eclipse.emf.cdo.server.IStoreChunkReader.Chunk;
+import org.eclipse.emf.cdo.server.db.IDBStore;
+import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
+import org.eclipse.emf.cdo.server.db.IDBStoreChunkReader;
+import org.eclipse.emf.cdo.server.db.IIDHandler;
+import org.eclipse.emf.cdo.server.db.IPreparedStatementCache;
+import org.eclipse.emf.cdo.server.db.IPreparedStatementCache.ReuseProbability;
+import org.eclipse.emf.cdo.server.db.mapping.IListMappingDeltaSupport;
+import org.eclipse.emf.cdo.server.db.mapping.IMappingStrategy;
+import org.eclipse.emf.cdo.server.db.mapping.ITypeMapping;
+import org.eclipse.emf.cdo.server.internal.db.CDODBSchema;
+import org.eclipse.emf.cdo.server.internal.db.bundle.OM;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+
+import org.eclipse.net4j.db.DBException;
+import org.eclipse.net4j.db.DBType;
+import org.eclipse.net4j.db.DBUtil;
+import org.eclipse.net4j.db.ddl.IDBField;
+import org.eclipse.net4j.db.ddl.IDBIndex.Type;
+import org.eclipse.net4j.db.ddl.IDBTable;
+import org.eclipse.net4j.util.ImplementationError;
+import org.eclipse.net4j.util.collection.MoveableList;
+import org.eclipse.net4j.util.om.trace.ContextTracer;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * This is a list-table mapping for audit mode. It is optimized for frequent insert operations at the list's end, which
+ * causes just 1 DB row to be changed. This is achieved by introducing a version range (columns cdo_version_added and
+ * cdo_version_removed) which records for which revisions a particular entry existed. Also, this mapping is mainly
+ * optimized for potentially very large lists: the need for having the complete list stored in memopy to do
+ * in-the-middle-moved and inserts is traded in for a few more DB access operations.
+ * 
+ * @author Eike Stepper
+ * @author Stefan Winkler
+ * @author Lothar Werzinger
+ */
+public class AuditListTableMappingWithRanges extends BasicAbstractListTableMapping implements IListMappingDeltaSupport
+{
+  private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG, AuditListTableMappingWithRanges.class);
+
+  /**
+   * Used to clean up lists for detached objects.
+   */
+  private static final int FINAL_VERSION = Integer.MAX_VALUE;
+
+  /**
+   * The table of this mapping.
+   */
+  private IDBTable table;
+
+  /**
+   * The type mapping for the value field.
+   */
+  private ITypeMapping typeMapping;
+
+  // --------- SQL strings - see initSQLStrings() -----------------
+  private String sqlSelectChunksPrefix;
+
+  private String sqlOrderByIndex;
+
+  private String sqlInsertEntry;
+
+  private String sqlDeleteEntry;
+
+  private String sqlRemoveEntry;
+
+  private String sqlUpdateIndex;
+
+  private String sqlGetValue;
+
+  private String sqlClearList;
+
+  private String sqlDeleteList;
+
+  public AuditListTableMappingWithRanges(IMappingStrategy mappingStrategy, EClass eClass, EStructuralFeature feature)
+  {
+    super(mappingStrategy, eClass, feature);
+    initTable();
+    initSQLStrings();
+  }
+
+  private void initTable()
+  {
+    IDBStore store = getMappingStrategy().getStore();
+    String tableName = getMappingStrategy().getTableName(getContainingClass(), getFeature());
+    table = store.getDBSchema().addTable(tableName);
+
+    IDBField[] dbFields = new IDBField[4];
+
+    dbFields[0] = table.addField(CDODBSchema.LIST_REVISION_ID, store.getIDHandler().getDBType());
+    dbFields[1] = table.addField(CDODBSchema.LIST_REVISION_VERSION_ADDED, DBType.INTEGER);
+    dbFields[2] = table.addField(CDODBSchema.LIST_REVISION_VERSION_REMOVED, DBType.INTEGER);
+    dbFields[3] = table.addField(CDODBSchema.LIST_IDX, DBType.INTEGER);
+
+    // add field for value
+    typeMapping = getMappingStrategy().createValueMapping(getFeature());
+    typeMapping.createDBField(table, CDODBSchema.LIST_VALUE);
+
+    // TODO think about indexes
+    // add table indexes
+    table.addIndex(Type.UNIQUE, dbFields);
+  }
+
+  public Collection<IDBTable> getDBTables()
+  {
+    return Arrays.asList(table);
+  }
+
+  private void initSQLStrings()
+  {
+    String tableName = getTable().getName();
+
+    // ---------------- read chunks ----------------------------
+    StringBuilder builder = new StringBuilder();
+    builder.append("SELECT "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_VALUE);
+    builder.append(" FROM "); //$NON-NLS-1$
+    builder.append(tableName);
+    builder.append(" WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_ID);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_VERSION_ADDED);
+    builder.append("<=? AND ("); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_VERSION_REMOVED);
+    builder.append(" IS NULL OR "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_VERSION_REMOVED);
+    builder.append(">?)"); //$NON-NLS-1$
+    sqlSelectChunksPrefix = builder.toString();
+
+    sqlOrderByIndex = " ORDER BY " + CDODBSchema.LIST_IDX; //$NON-NLS-1$
+
+    // ----------------- insert entry -----------------
+    builder = new StringBuilder("INSERT INTO "); //$NON-NLS-1$
+    builder.append(tableName);
+    builder.append("("); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_ID);
+    builder.append(","); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_VERSION_ADDED);
+    builder.append(","); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_VERSION_REMOVED);
+    builder.append(","); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_IDX);
+    builder.append(","); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_VALUE);
+    builder.append(") VALUES (?, ?, NULL, ?, ?)"); //$NON-NLS-1$
+    sqlInsertEntry = builder.toString();
+
+    // ----------------- remove current entry -----------------
+    builder = new StringBuilder("UPDATE "); //$NON-NLS-1$
+    builder.append(getTable());
+    builder.append(" SET "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_VERSION_REMOVED);
+    builder.append("=? "); //$NON-NLS-1$
+    builder.append(" WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_ID);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_IDX);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_VERSION_REMOVED);
+    builder.append(" IS NULL"); //$NON-NLS-1$
+    sqlRemoveEntry = builder.toString();
+
+    // ----------------- delete temporary entry -----------------
+    builder = new StringBuilder("DELETE FROM "); //$NON-NLS-1$
+    builder.append(getTable());
+    builder.append(" WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_ID);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_IDX);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_VERSION_ADDED);
+    builder.append("=?"); //$NON-NLS-1$
+    sqlDeleteEntry = builder.toString();
+
+    // ----------------- update index -----------------
+    builder = new StringBuilder("UPDATE "); //$NON-NLS-1$
+    builder.append(getTable());
+    builder.append(" SET "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_IDX);
+    builder.append("=? WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_ID);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_VERSION_ADDED);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_IDX);
+    builder.append("=?"); //$NON-NLS-1$
+    sqlUpdateIndex = builder.toString();
+
+    // ----------------- get current value -----------------
+    builder = new StringBuilder("SELECT "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_VALUE);
+    builder.append(" FROM "); //$NON-NLS-1$
+    builder.append(getTable());
+    builder.append(" WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_ID);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_IDX);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_VERSION_REMOVED);
+    builder.append(" IS NULL"); //$NON-NLS-1$
+    sqlGetValue = builder.toString();
+
+    // ----------- clear list items -------------------------
+    builder = new StringBuilder("UPDATE "); //$NON-NLS-1$
+    builder.append(getTable());
+    builder.append(" SET "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_VERSION_REMOVED);
+    builder.append("=? "); //$NON-NLS-1$
+    builder.append(" WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_ID);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_VERSION_REMOVED);
+    builder.append(" IS NULL"); //$NON-NLS-1$
+    sqlClearList = builder.toString();
+
+    // ----------- delete temporary list items -------------------------
+    builder = new StringBuilder("DELETE FROM "); //$NON-NLS-1$
+    builder.append(getTable());
+    builder.append(" WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_ID);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_VERSION_ADDED);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_VERSION_REMOVED);
+    builder.append(" IS NULL"); //$NON-NLS-1$
+    sqlDeleteList = builder.toString();
+  }
+
+  protected final IDBTable getTable()
+  {
+    return table;
+  }
+
+  protected final ITypeMapping getTypeMapping()
+  {
+    return typeMapping;
+  }
+
+  public void readValues(IDBStoreAccessor accessor, InternalCDORevision revision, int listChunk)
+  {
+    MoveableList<Object> list = revision.getList(getFeature());
+    if (listChunk == 0 || list.size() == 0)
+    {
+      // nothing to read take shortcut
+      return;
+    }
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Reading list values for feature {0}.{1} of {2}v{3}", getContainingClass().getName(), //$NON-NLS-1$
+          getFeature().getName(), revision.getID(), revision.getVersion());
+    }
+
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+    ResultSet resultSet = null;
+
+    try
+    {
+      String sql = sqlSelectChunksPrefix + sqlOrderByIndex;
+      stmt = statementCache.getPreparedStatement(sql, ReuseProbability.HIGH);
+      idHandler.setCDOID(stmt, 1, revision.getID());
+      stmt.setInt(2, revision.getVersion());
+      stmt.setInt(3, revision.getVersion());
+
+      if (listChunk != CDORevision.UNCHUNKED)
+      {
+        stmt.setMaxRows(listChunk); // optimization - don't read unneeded rows.
+      }
+
+      resultSet = stmt.executeQuery();
+
+      int currentIndex = 0;
+      while ((listChunk == CDORevision.UNCHUNKED || --listChunk >= 0) && resultSet.next())
+      {
+        Object value = typeMapping.readValue(resultSet);
+        if (TRACER.isEnabled())
+        {
+          TRACER.format("Read value for index {0} from result set: {1}", list.size(), value); //$NON-NLS-1$
+        }
+
+        list.set(currentIndex++, value);
+      }
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex);
+    }
+    finally
+    {
+      DBUtil.close(resultSet);
+      statementCache.releasePreparedStatement(stmt);
+    }
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Reading {4} list values done for feature {0}.{1} of {2}v{3}", //$NON-NLS-1$
+          getContainingClass().getName(), getFeature().getName(), revision.getID(), revision.getVersion(), list.size());
+    }
+  }
+
+  public final void readChunks(IDBStoreChunkReader chunkReader, List<Chunk> chunks, String where)
+  {
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Reading list chunk values for feature() {0}.{1} of {2}v{3}", getContainingClass().getName(), //$NON-NLS-1$
+          getFeature().getName(), chunkReader.getRevision().getID(), chunkReader.getRevision().getVersion());
+    }
+
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = chunkReader.getAccessor().getStatementCache();
+    PreparedStatement stmt = null;
+    ResultSet resultSet = null;
+
+    try
+    {
+      StringBuilder builder = new StringBuilder(sqlSelectChunksPrefix);
+      if (where != null)
+      {
+        builder.append(" AND "); //$NON-NLS-1$
+        builder.append(where);
+      }
+
+      builder.append(sqlOrderByIndex);
+
+      String sql = builder.toString();
+      stmt = statementCache.getPreparedStatement(sql, ReuseProbability.LOW);
+      idHandler.setCDOID(stmt, 1, chunkReader.getRevision().getID());
+      stmt.setInt(2, chunkReader.getRevision().getVersion());
+      stmt.setInt(3, chunkReader.getRevision().getVersion());
+
+      resultSet = stmt.executeQuery();
+
+      Chunk chunk = null;
+      int chunkSize = 0;
+      int chunkIndex = 0;
+      int indexInChunk = 0;
+
+      while (resultSet.next())
+      {
+        Object value = typeMapping.readValue(resultSet);
+
+        if (chunk == null)
+        {
+          chunk = chunks.get(chunkIndex++);
+          chunkSize = chunk.size();
+
+          if (TRACER.isEnabled())
+          {
+            TRACER.format("Current chunk no. {0} is [start = {1}, size = {2}]", chunkIndex - 1, chunk.getStartIndex(), //$NON-NLS-1$
+                chunkSize);
+          }
+        }
+
+        if (TRACER.isEnabled())
+        {
+          TRACER.format("Read value for chunk index {0} from result set: {1}", indexInChunk, value); //$NON-NLS-1$
+        }
+
+        chunk.add(indexInChunk++, value);
+        if (indexInChunk == chunkSize)
+        {
+          if (TRACER.isEnabled())
+          {
+            TRACER.format("Chunk finished"); //$NON-NLS-1$
+          }
+
+          chunk = null;
+          indexInChunk = 0;
+        }
+      }
+
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Reading list chunk values done for feature() {0}.{1} of {2}v{3}", //$NON-NLS-1$
+            getContainingClass().getName(), getFeature().getName(), chunkReader.getRevision().getID(), chunkReader
+                .getRevision().getVersion());
+      }
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex);
+    }
+    finally
+    {
+      DBUtil.close(resultSet);
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  public void writeValues(IDBStoreAccessor accessor, InternalCDORevision revision)
+  {
+    CDOList values = revision.getList(getFeature());
+
+    int idx = 0;
+    for (Object element : values)
+    {
+      writeValue(accessor, revision, idx++, element);
+    }
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Writing done"); //$NON-NLS-1$
+    }
+  }
+
+  protected final void writeValue(IDBStoreAccessor accessor, CDORevision revision, int index, Object value)
+  {
+    if (TRACER.isEnabled())
+    {
+      TRACER
+          .format(
+              "Writing value for feature {0}.{1} index {2} of {3}v{4} : {5}", //$NON-NLS-1$
+              getContainingClass().getName(), getFeature().getName(), index, revision.getID(), revision.getVersion(),
+              value);
+    }
+
+    addEntry(accessor, revision.getID(), revision.getVersion(), index, value);
+  }
+
+  /**
+   * Clear a list of a given revision.
+   * 
+   * @param accessor
+   *          the accessor to use
+   * @param id
+   *          the id of the revision from which to remove all items
+   */
+  public void clearList(IDBStoreAccessor accessor, CDOID id, int oldVersion, int newVersion)
+  {
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmtDeleteTemp = null;
+    PreparedStatement stmtClear = null;
+
+    try
+    {
+      // delete temporary entries
+      stmtDeleteTemp = statementCache.getPreparedStatement(sqlDeleteList, ReuseProbability.HIGH);
+      idHandler.setCDOID(stmtDeleteTemp, 1, id);
+      stmtDeleteTemp.setInt(2, newVersion);
+
+      int result = DBUtil.update(stmtDeleteTemp, false);
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("DeleteList result: {0}", result); //$NON-NLS-1$
+      }
+
+      // clear rest of the list
+      stmtClear = statementCache.getPreparedStatement(sqlClearList, ReuseProbability.HIGH);
+      stmtClear.setInt(1, newVersion);
+      idHandler.setCDOID(stmtClear, 2, id);
+
+      result = DBUtil.update(stmtClear, false);
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("ClearList result: {0}", result); //$NON-NLS-1$
+      }
+    }
+    catch (SQLException e)
+    {
+      throw new DBException(e);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmtDeleteTemp);
+      statementCache.releasePreparedStatement(stmtClear);
+    }
+  }
+
+  public void objectDetached(IDBStoreAccessor accessor, CDOID id, long revised)
+  {
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("objectRevised {0}: {1}", id, revised); //$NON-NLS-1$
+    }
+
+    CDOBranch main = getMappingStrategy().getStore().getRepository().getBranchManager().getMainBranch();
+
+    // get revision from cache to find out version number
+    CDORevision revision = getMappingStrategy().getStore().getRepository().getRevisionManager()
+        .getRevision(id, main.getHead(), /* chunksize = */0, CDORevision.DEPTH_NONE, true);
+
+    // set cdo_revision_removed for all list items (so we have no NULL values)
+    clearList(accessor, id, revision.getVersion(), FINAL_VERSION);
+  }
+
+  public void processDelta(final IDBStoreAccessor accessor, final CDOID id, final int branchId, int oldVersion,
+      final int newVersion, long created, CDOListFeatureDelta delta)
+  {
+    IRepository repo = accessor.getStore().getRepository();
+    InternalCDORevision originalRevision = (InternalCDORevision)repo.getRevisionManager().getRevision(id,
+        repo.getBranchManager().getMainBranch().getHead(), /* chunksize = */0, CDORevision.DEPTH_NONE, true);
+
+    int oldListSize = originalRevision.getList(getFeature()).size();
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("ListTableMapping.processDelta for revision {0} - previous list size: {1}", originalRevision, //$NON-NLS-1$
+          oldListSize);
+    }
+
+    // let the visitor collect the changes
+    ListDeltaVisitor visitor = new ListDeltaVisitor(accessor, originalRevision, oldVersion, newVersion);
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Processing deltas..."); //$NON-NLS-1$
+    }
+
+    for (CDOFeatureDelta listDelta : delta.getListChanges())
+    {
+      listDelta.accept(visitor);
+    }
+  }
+
+  /**
+   * @author Stefan Winkler
+   */
+  private class ListDeltaVisitor implements CDOFeatureDeltaVisitor
+  {
+    private IDBStoreAccessor accessor;
+
+    private CDOID id;
+
+    private int oldVersion;
+
+    private int newVersion;
+
+    private int lastIndex;
+
+    public ListDeltaVisitor(IDBStoreAccessor accessor, InternalCDORevision originalRevision, int oldVersion,
+        int newVersion)
+    {
+      this.accessor = accessor;
+      id = originalRevision.getID();
+      this.oldVersion = oldVersion;
+      this.newVersion = newVersion;
+      lastIndex = originalRevision.getList(getFeature()).size() - 1;
+    }
+
+    public void visit(CDOMoveFeatureDelta delta)
+    {
+      int fromIdx = delta.getOldPosition();
+      int toIdx = delta.getNewPosition();
+
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Delta Moving: {0} to {1}", fromIdx, toIdx); //$NON-NLS-1$
+      }
+
+      Object value = getValue(accessor, id, fromIdx);
+
+      // remove the item
+      removeEntry(accessor, id, oldVersion, newVersion, fromIdx);
+
+      // adjust indexes and shift either up or down
+      if (fromIdx < toIdx)
+      {
+        moveOneUp(accessor, id, oldVersion, newVersion, fromIdx + 1, toIdx);
+      }
+      else
+      { // fromIdx > toIdx here
+        moveOneDown(accessor, id, oldVersion, newVersion, toIdx, fromIdx - 1);
+      }
+
+      // create the item
+      addEntry(accessor, id, newVersion, toIdx, value);
+    }
+
+    public void visit(CDOAddFeatureDelta delta)
+    {
+      int startIndex = delta.getIndex();
+      int endIndex = lastIndex;
+
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Delta Adding at: {0}", startIndex); //$NON-NLS-1$
+      }
+
+      if (startIndex <= endIndex)
+      {
+        // make room for the new item
+        moveOneDown(accessor, id, oldVersion, newVersion, startIndex, endIndex);
+      }
+
+      // create the item
+      addEntry(accessor, id, newVersion, startIndex, delta.getValue());
+
+      ++lastIndex;
+    }
+
+    public void visit(CDORemoveFeatureDelta delta)
+    {
+      int startIndex = delta.getIndex();
+      int endIndex = lastIndex;
+
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Delta Removing at: {0}", startIndex); //$NON-NLS-1$
+      }
+
+      // remove the item
+      removeEntry(accessor, id, oldVersion, newVersion, startIndex);
+
+      // make room for the new item
+      moveOneUp(accessor, id, oldVersion, newVersion, startIndex + 1, endIndex);
+
+      --lastIndex;
+    }
+
+    public void visit(CDOSetFeatureDelta delta)
+    {
+      int index = delta.getIndex();
+
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Delta Setting at: {0}", index); //$NON-NLS-1$
+      }
+
+      // remove the item
+      removeEntry(accessor, id, oldVersion, newVersion, index);
+
+      // create the item
+      addEntry(accessor, id, newVersion, index, delta.getValue());
+    }
+
+    public void visit(CDOUnsetFeatureDelta delta)
+    {
+      if (delta.getFeature().isUnsettable())
+      {
+        throw new ImplementationError("Should not be called"); //$NON-NLS-1$
+      }
+
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Delta Unsetting"); //$NON-NLS-1$
+      }
+
+      clearList(accessor, id, oldVersion, newVersion);
+      lastIndex = -1;
+    }
+
+    public void visit(CDOListFeatureDelta delta)
+    {
+      throw new ImplementationError("Should not be called"); //$NON-NLS-1$
+    }
+
+    public void visit(CDOClearFeatureDelta delta)
+    {
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Delta Clearing"); //$NON-NLS-1$
+      }
+
+      clearList(accessor, id, oldVersion, newVersion);
+      lastIndex = -1;
+    }
+
+    public void visit(CDOContainerFeatureDelta delta)
+    {
+      throw new ImplementationError("Should not be called"); //$NON-NLS-1$
+    }
+
+    private void moveOneUp(IDBStoreAccessor accessor, CDOID id, int oldVersion, int newVersion, int startIndex,
+        int endIndex)
+    {
+      IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+      IPreparedStatementCache statementCache = accessor.getStatementCache();
+      PreparedStatement stmt = null;
+
+      try
+      {
+        stmt = statementCache.getPreparedStatement(sqlUpdateIndex, ReuseProbability.HIGH);
+
+        for (int index = startIndex; index <= endIndex; ++index)
+        {
+          if (TRACER.isEnabled())
+          {
+            TRACER.format("moveOneUp moving: {0} -> {1}", index, index - 1); //$NON-NLS-1$
+          }
+
+          int column = 1;
+          stmt.setInt(column++, index - 1);
+          idHandler.setCDOID(stmt, column++, id);
+          stmt.setInt(column++, newVersion);
+          stmt.setInt(column++, index);
+
+          int result = DBUtil.update(stmt, false);
+          switch (result)
+          {
+          case 0:
+            Object value = getValue(accessor, id, index);
+            if (TRACER.isEnabled())
+            {
+              TRACER.format("moveOneUp remove: {0}", index); //$NON-NLS-1$
+            }
+
+            removeEntry(accessor, id, oldVersion, newVersion, index);
+            if (TRACER.isEnabled())
+            {
+              TRACER.format("moveOneUp add: {0}", index - 1); //$NON-NLS-1$
+            }
+
+            addEntry(accessor, id, newVersion, index - 1, value);
+            break;
+
+          case 1:
+            if (TRACER.isEnabled())
+            {
+              TRACER.format("moveOneUp updated: {0} -> {1}", index, index - 1); //$NON-NLS-1$
+            }
+
+            break;
+
+          default:
+            if (TRACER.isEnabled())
+            {
+              TRACER.format("moveOneUp Too many results: {0} -> {1}: {2}", index, index + 1, result); //$NON-NLS-1$
+            }
+
+            throw new DBException("Too many results"); //$NON-NLS-1$
+          }
+        }
+      }
+      catch (SQLException e)
+      {
+        throw new DBException(e);
+      }
+      finally
+      {
+        statementCache.releasePreparedStatement(stmt);
+      }
+    }
+
+    private void moveOneDown(IDBStoreAccessor accessor, CDOID id, int oldVersion, int newVersion, int startIndex,
+        int endIndex)
+    {
+      IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+      IPreparedStatementCache statementCache = accessor.getStatementCache();
+      PreparedStatement stmt = null;
+
+      try
+      {
+        stmt = statementCache.getPreparedStatement(sqlUpdateIndex, ReuseProbability.HIGH);
+
+        for (int index = endIndex; index >= startIndex; --index)
+        {
+          if (TRACER.isEnabled())
+          {
+            TRACER.format("moveOneDown moving: {0} -> {1}", index, index + 1); //$NON-NLS-1$
+          }
+
+          int column = 1;
+          stmt.setInt(column++, index + 1);
+          idHandler.setCDOID(stmt, column++, id);
+          stmt.setInt(column++, newVersion);
+          stmt.setInt(column++, index);
+
+          int result = DBUtil.update(stmt, false);
+          switch (result)
+          {
+          case 0:
+            Object value = getValue(accessor, id, index);
+            if (TRACER.isEnabled())
+            {
+              TRACER.format("moveOneDown remove: {0}", index); //$NON-NLS-1$
+            }
+
+            removeEntry(accessor, id, oldVersion, newVersion, index);
+            if (TRACER.isEnabled())
+            {
+              TRACER.format("moveOneDown add: {0}", index + 1); //$NON-NLS-1$
+            }
+
+            addEntry(accessor, id, newVersion, index + 1, value);
+            break;
+
+          case 1:
+            if (TRACER.isEnabled())
+            {
+              TRACER.format("moveOneDown updated: {0} -> {1}", index, index + 1); //$NON-NLS-1$
+            }
+
+            break;
+
+          default:
+            if (TRACER.isEnabled())
+            {
+              TRACER.format("moveOneDown Too many results: {0} -> {1}: {2}", index, index + 1, result); //$NON-NLS-1$
+            }
+
+            throw new DBException("Too many results"); //$NON-NLS-1$
+          }
+        }
+      }
+      catch (SQLException e)
+      {
+        throw new DBException(e);
+      }
+      finally
+      {
+        statementCache.releasePreparedStatement(stmt);
+      }
+    }
+  }
+
+  private void addEntry(IDBStoreAccessor accessor, CDOID id, int version, int index, Object value)
+  {
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Adding value for feature() {0}.{1} index {2} of {3}v{4} : {5}", //$NON-NLS-1$
+          getContainingClass().getName(), getFeature().getName(), index, id, version, value);
+    }
+
+    try
+    {
+      stmt = statementCache.getPreparedStatement(sqlInsertEntry, ReuseProbability.HIGH);
+
+      int column = 1;
+      idHandler.setCDOID(stmt, column++, id);
+      stmt.setInt(column++, version);
+      stmt.setInt(column++, index);
+      typeMapping.setValue(stmt, column++, value);
+
+      DBUtil.update(stmt, true);
+    }
+    catch (SQLException e)
+    {
+      throw new DBException(e);
+    }
+    catch (IllegalStateException e)
+    {
+      throw new DBException(e);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  private void removeEntry(IDBStoreAccessor accessor, CDOID id, int oldVersion, int newVersion, int index)
+  {
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Removing value for feature() {0}.{1} index {2} of {3}v{4}", //$NON-NLS-1$
+          getContainingClass().getName(), getFeature().getName(), index, id, newVersion);
+    }
+
+    try
+    {
+      // try to delete a temporary entry first
+      stmt = statementCache.getPreparedStatement(sqlDeleteEntry, ReuseProbability.HIGH);
+
+      int column = 1;
+      idHandler.setCDOID(stmt, column++, id);
+      stmt.setInt(column++, index);
+      stmt.setInt(column++, newVersion);
+
+      int result = DBUtil.update(stmt, false);
+      if (result == 1)
+      {
+        if (TRACER.isEnabled())
+        {
+          TRACER.format("removeEntry deleted: {0}", index); //$NON-NLS-1$
+        }
+      }
+      else if (result > 1)
+      {
+        if (TRACER.isEnabled())
+        {
+          TRACER.format("removeEntry Too many results: {0}: {1}", index, result); //$NON-NLS-1$
+        }
+
+        throw new DBException("Too many results"); //$NON-NLS-1$
+      }
+      else
+      {
+        // no temporary entry found, so mark the entry as removed
+        statementCache.releasePreparedStatement(stmt);
+        stmt = statementCache.getPreparedStatement(sqlRemoveEntry, ReuseProbability.HIGH);
+
+        column = 1;
+        stmt.setInt(column++, newVersion);
+        idHandler.setCDOID(stmt, column++, id);
+        stmt.setInt(column++, index);
+
+        DBUtil.update(stmt, true);
+      }
+    }
+    catch (SQLException e)
+    {
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Removing value for feature() {0}.{1} index {2} of {3}v{4} FAILED {5}", //$NON-NLS-1$
+            getContainingClass().getName(), getFeature().getName(), index, id, newVersion, e.getMessage());
+      }
+
+      throw new DBException(e);
+    }
+    catch (IllegalStateException e)
+    {
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Removing value for feature() {0}.{1} index {2} of {3}v{4} FAILED {5}", //$NON-NLS-1$
+            getContainingClass().getName(), getFeature().getName(), index, id, newVersion, e.getMessage());
+      }
+
+      throw new DBException(e);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  private Object getValue(IDBStoreAccessor accessor, CDOID id, int index)
+  {
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+    Object result = null;
+
+    try
+    {
+      stmt = statementCache.getPreparedStatement(sqlGetValue, ReuseProbability.HIGH);
+
+      int column = 1;
+      idHandler.setCDOID(stmt, column++, id);
+      stmt.setInt(column++, index);
+
+      ResultSet resultSet = stmt.executeQuery();
+      if (!resultSet.next())
+      {
+        throw new DBException("getValue() expects exactly one result");
+      }
+
+      result = typeMapping.readValue(resultSet);
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Read value (index {0}) from result set: {1}", index, result); //$NON-NLS-1$
+      }
+    }
+    catch (SQLException e)
+    {
+      throw new DBException(e);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+
+    return result;
+  }
+
+  public final boolean queryXRefs(IDBStoreAccessor accessor, String mainTableName, String mainTableWhere,
+      QueryXRefsContext context, String idString)
+  {
+
+    String tableName = getTable().getName();
+    String listJoin = getMappingStrategy().getListJoin("a_t", "l_t");
+
+    StringBuilder builder = new StringBuilder();
+    builder.append("SELECT l_t."); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_ID);
+    builder.append(", l_t."); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_VALUE);
+    builder.append(", l_t."); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_IDX);
+    builder.append(" FROM "); //$NON-NLS-1$
+    builder.append(tableName);
+    builder.append(" AS l_t, ");//$NON-NLS-1$
+    builder.append(mainTableName);
+    builder.append(" AS a_t WHERE ");//$NON-NLS-1$
+    builder.append("a_t." + mainTableWhere);//$NON-NLS-1$
+    builder.append(listJoin);
+    builder.append(" AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_VALUE);
+    builder.append(" IN "); //$NON-NLS-1$
+    builder.append(idString);
+    String sql = builder.toString();
+
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    ResultSet resultSet = null;
+    Statement stmt = null;
+
+    try
+    {
+      stmt = accessor.getConnection().createStatement();
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Query XRefs (list): {0}", sql);
+      }
+
+      resultSet = stmt.executeQuery(sql);
+      while (resultSet.next())
+      {
+        CDOID sourceID = idHandler.getCDOID(resultSet, 1);
+        CDOID targetID = idHandler.getCDOID(resultSet, 2);
+        int idx = resultSet.getInt(3);
+
+        boolean more = context.addXRef(targetID, sourceID, (EReference)getFeature(), idx);
+        if (TRACER.isEnabled())
+        {
+          TRACER.format("  add XRef to context: src={0}, tgt={1}, idx={2}", sourceID, targetID, idx);
+        }
+
+        if (!more)
+        {
+          if (TRACER.isEnabled())
+          {
+            TRACER.format("  result limit reached. Ignoring further results.");
+          }
+
+          return false;
+        }
+      }
+
+      return true;
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex);
+    }
+    finally
+    {
+      DBUtil.close(resultSet);
+      DBUtil.close(stmt);
+    }
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/BasicAbstractListTableMapping.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/BasicAbstractListTableMapping.java
new file mode 100644
index 0000000..6e2e1b6
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/BasicAbstractListTableMapping.java
@@ -0,0 +1,52 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Stefan Winkler - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server.internal.db.mapping.horizontal;
+
+import org.eclipse.emf.cdo.server.db.mapping.IListMapping;
+import org.eclipse.emf.cdo.server.db.mapping.IMappingStrategy;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+/**
+ * @author Stefan Winkler
+ */
+public abstract class BasicAbstractListTableMapping implements IListMapping
+{
+  private IMappingStrategy mappingStrategy;
+
+  private EClass containingClass;
+
+  private EStructuralFeature feature;
+
+  public BasicAbstractListTableMapping(IMappingStrategy mappingStrategy, EClass containingClass,
+      EStructuralFeature feature)
+  {
+    this.mappingStrategy = mappingStrategy;
+    this.containingClass = containingClass;
+    this.feature = feature;
+  }
+
+  public final IMappingStrategy getMappingStrategy()
+  {
+    return mappingStrategy;
+  }
+
+  public final EClass getContainingClass()
+  {
+    return containingClass;
+  }
+
+  public final EStructuralFeature getFeature()
+  {
+    return feature;
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/BranchingFeatureMapTableMapping.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/BranchingFeatureMapTableMapping.java
new file mode 100644
index 0000000..056ccc3
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/BranchingFeatureMapTableMapping.java
@@ -0,0 +1,72 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others. 
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - Bug 271444: [DB] Multiple refactorings bug 271444
+ *    Christopher Albert - Bug 254455: [DB] Support FeatureMaps bug 254455
+ *    Stefan Winkler - derived branch mapping from audit mapping  
+ */
+package org.eclipse.emf.cdo.server.internal.db.mapping.horizontal;
+
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
+import org.eclipse.emf.cdo.server.db.mapping.IMappingStrategy;
+import org.eclipse.emf.cdo.server.internal.db.CDODBSchema;
+
+import org.eclipse.net4j.db.DBType;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+
+/**
+ * This is a featuremap-table mapping for audit mode. It has ID and version columns and no delta support.
+ * 
+ * @author Eike Stepper
+ * @author Stefan Winkler
+ * @since 3.0
+ */
+public class BranchingFeatureMapTableMapping extends AbstractFeatureMapTableMapping
+{
+  private FieldInfo[] keyFields;
+
+  public BranchingFeatureMapTableMapping(IMappingStrategy mappingStrategy, EClass eClass, EStructuralFeature feature)
+  {
+    super(mappingStrategy, eClass, feature);
+  }
+
+  @Override
+  protected FieldInfo[] getKeyFields()
+  {
+    if (keyFields == null)
+    {
+      keyFields = new FieldInfo[] {
+          new FieldInfo(CDODBSchema.FEATUREMAP_REVISION_ID, getMappingStrategy().getStore().getIDHandler().getDBType()),
+          new FieldInfo(CDODBSchema.FEATUREMAP_BRANCH, DBType.INTEGER),
+          new FieldInfo(CDODBSchema.FEATUREMAP_VERSION, DBType.INTEGER) };
+    }
+
+    return keyFields;
+  }
+
+  @Override
+  protected void setKeyFields(PreparedStatement stmt, CDORevision revision) throws SQLException
+  {
+    getMappingStrategy().getStore().getIDHandler().setCDOID(stmt, 1, revision.getID());
+    stmt.setInt(2, revision.getBranch().getID());
+    stmt.setInt(3, revision.getVersion());
+  }
+
+  public void objectDetached(IDBStoreAccessor accessor, CDOID id, long revised)
+  {
+    // the audit list mapping does not care about revised references -> NOP
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/BranchingFeatureMapTableMappingWithRanges.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/BranchingFeatureMapTableMappingWithRanges.java
new file mode 100644
index 0000000..b1458ae
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/BranchingFeatureMapTableMappingWithRanges.java
@@ -0,0 +1,1502 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Stefan Winkler - initial API and implementation taken from AuditFeatureMapTableMappingWithRanges
+ *    Stefan Winkler - Bug 329025: [DB] Support branching for range-based mapping strategy
+ */
+package org.eclipse.emf.cdo.server.internal.db.mapping.horizontal;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.revision.CDOList;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionUtil;
+import org.eclipse.emf.cdo.common.revision.delta.CDOAddFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOClearFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOContainerFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDeltaVisitor;
+import org.eclipse.emf.cdo.common.revision.delta.CDOListFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOMoveFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDORemoveFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOSetFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOUnsetFeatureDelta;
+import org.eclipse.emf.cdo.server.IStoreAccessor.QueryXRefsContext;
+import org.eclipse.emf.cdo.server.IStoreChunkReader;
+import org.eclipse.emf.cdo.server.IStoreChunkReader.Chunk;
+import org.eclipse.emf.cdo.server.db.IDBStore;
+import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
+import org.eclipse.emf.cdo.server.db.IDBStoreChunkReader;
+import org.eclipse.emf.cdo.server.db.IIDHandler;
+import org.eclipse.emf.cdo.server.db.IPreparedStatementCache;
+import org.eclipse.emf.cdo.server.db.IPreparedStatementCache.ReuseProbability;
+import org.eclipse.emf.cdo.server.db.mapping.IListMappingDeltaSupport;
+import org.eclipse.emf.cdo.server.db.mapping.IMappingStrategy;
+import org.eclipse.emf.cdo.server.db.mapping.ITypeMapping;
+import org.eclipse.emf.cdo.server.internal.db.CDODBSchema;
+import org.eclipse.emf.cdo.server.internal.db.bundle.OM;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+
+import org.eclipse.net4j.db.DBException;
+import org.eclipse.net4j.db.DBType;
+import org.eclipse.net4j.db.DBUtil;
+import org.eclipse.net4j.db.ddl.IDBField;
+import org.eclipse.net4j.db.ddl.IDBIndex.Type;
+import org.eclipse.net4j.db.ddl.IDBTable;
+import org.eclipse.net4j.util.ImplementationError;
+import org.eclipse.net4j.util.collection.MoveableList;
+import org.eclipse.net4j.util.om.trace.ContextTracer;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.util.FeatureMap;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This is a featuremap-table mapping for audit mode. It is optimized for frequent insert operations at the list's end,
+ * which causes just 1 DB row to be changed. This is achieved by introducing a version range (columns
+ * {@link CDODBSchema#LIST_REVISION_VERSION_ADDED cdo_version_added} and
+ * {@link CDODBSchema#LIST_REVISION_VERSION_REMOVED cdo_version_removed}) which records for which revisions a particular
+ * entry existed. Also, this mapping is mainly optimized for potentially very large lists: the need for having the
+ * complete list stored in memory to do in-the-middle-moved and inserts is traded in for a few more DB access
+ * operations.
+ * 
+ * @author Eike Stepper
+ * @author Stefan Winkler
+ * @author Lothar Werzinger
+ * @since 3.0
+ */
+public class BranchingFeatureMapTableMappingWithRanges extends BasicAbstractListTableMapping implements
+    IListMappingDeltaSupport
+{
+  private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG,
+      BranchingFeatureMapTableMappingWithRanges.class);
+
+  /**
+   * Used to clean up lists for detached objects.
+   */
+  private static final int FINAL_VERSION = Integer.MAX_VALUE;
+
+  /**
+   * The table of this mapping.
+   */
+  private IDBTable table;
+
+  /**
+   * The tags mapped to column names
+   */
+  private HashMap<CDOID, String> tagMap;
+
+  /**
+   * Column name Set
+   */
+  private List<String> columnNames;
+
+  /**
+   * The type mappings for the value fields.
+   */
+  private Map<CDOID, ITypeMapping> typeMappings;
+
+  private List<DBType> dbTypes;
+
+  // --------- SQL strings - see initSQLStrings() -----------------
+  private String sqlSelectChunksPrefix;
+
+  private String sqlOrderByIndex;
+
+  private String sqlInsert;
+
+  private String sqlRemoveEntry;
+
+  private String sqlDeleteEntry;
+
+  private String sqlUpdateIndex;
+
+  private String sqlGetValue;
+
+  private String sqlClearList;
+
+  public BranchingFeatureMapTableMappingWithRanges(IMappingStrategy mappingStrategy, EClass eClass,
+      EStructuralFeature feature)
+  {
+    super(mappingStrategy, eClass, feature);
+    initDBTypes();
+    initTable();
+    initSQLStrings();
+  }
+
+  private void initDBTypes()
+  {
+    // TODO add annotation processing here ...
+    ITypeMapping.Registry registry = ITypeMapping.Registry.INSTANCE;
+    dbTypes = new ArrayList<DBType>(registry.getDefaultFeatureMapDBTypes());
+  }
+
+  private void initTable()
+  {
+    IDBStore store = getMappingStrategy().getStore();
+    String tableName = getMappingStrategy().getTableName(getContainingClass(), getFeature());
+    table = store.getDBSchema().addTable(tableName);
+
+    // add fields for CDOID
+    IDBField idField = table.addField(CDODBSchema.FEATUREMAP_REVISION_ID, store.getIDHandler().getDBType());
+
+    IDBField branchField = table.addField(CDODBSchema.LIST_REVISION_BRANCH, DBType.INTEGER);
+
+    // add fields for version range
+    IDBField versionAddedField = table.addField(CDODBSchema.FEATUREMAP_VERSION_ADDED, DBType.INTEGER);
+    IDBField versionRemovedField = table.addField(CDODBSchema.FEATUREMAP_VERSION_REMOVED, DBType.INTEGER);
+
+    // add field for list index
+    IDBField idxField = table.addField(CDODBSchema.FEATUREMAP_IDX, DBType.INTEGER);
+
+    // add field for FeatureMap tag (MetaID for Feature in CDO registry)
+    IDBField tagField = table.addField(CDODBSchema.FEATUREMAP_TAG, store.getIDHandler().getDBType());
+
+    tagMap = new HashMap<CDOID, String>();
+    typeMappings = new HashMap<CDOID, ITypeMapping>();
+    columnNames = new ArrayList<String>();
+
+    // create columns for all DBTypes
+    for (DBType type : getDBTypes())
+    {
+      String column = CDODBSchema.FEATUREMAP_VALUE + "_" + type.name();
+      table.addField(column, type);
+      columnNames.add(column);
+    }
+
+    table.addIndex(Type.NON_UNIQUE, idField);
+    table.addIndex(Type.NON_UNIQUE, branchField);
+    table.addIndex(Type.NON_UNIQUE, versionAddedField);
+    table.addIndex(Type.NON_UNIQUE, versionRemovedField);
+    table.addIndex(Type.NON_UNIQUE, idxField);
+    table.addIndex(Type.NON_UNIQUE, tagField);
+  }
+
+  public Collection<IDBTable> getDBTables()
+  {
+    return Arrays.asList(table);
+  }
+
+  private void initSQLStrings()
+  {
+    String tableName = getTable().getName();
+
+    // ---------------- SELECT to read chunks ----------------------------
+    StringBuilder builder = new StringBuilder();
+    builder.append("SELECT "); //$NON-NLS-1$
+
+    builder.append(CDODBSchema.FEATUREMAP_IDX);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_TAG);
+    builder.append(", "); //$NON-NLS-1$
+
+    Iterator<String> iter = columnNames.iterator();
+    while (iter.hasNext())
+    {
+      builder.append(iter.next());
+      if (iter.hasNext())
+      {
+        builder.append(", "); //$NON-NLS-1$
+      }
+    }
+
+    builder.append(" FROM "); //$NON-NLS-1$
+    builder.append(tableName);
+    builder.append(" WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_REVISION_ID);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_BRANCH);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_VERSION_ADDED);
+    builder.append("<=? AND ("); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_VERSION_REMOVED);
+    builder.append(" IS NULL OR "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_VERSION_REMOVED);
+    builder.append(">?)"); //$NON-NLS-1$
+    sqlSelectChunksPrefix = builder.toString();
+
+    sqlOrderByIndex = " ORDER BY " + CDODBSchema.FEATUREMAP_IDX; //$NON-NLS-1$
+
+    // ----------------- INSERT - prefix -----------------
+    builder = new StringBuilder("INSERT INTO "); //$NON-NLS-1$
+    builder.append(tableName);
+    builder.append("("); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_REVISION_ID);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_BRANCH);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_VERSION_ADDED);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_VERSION_REMOVED);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_IDX);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_TAG);
+
+    for (int i = 0; i < columnNames.size(); i++)
+    {
+      builder.append(", "); //$NON-NLS-1$
+      builder.append(columnNames.get(i));
+    }
+
+    builder.append(") VALUES (?, ?, ?, ?, ?, ?"); //$NON-NLS-1$
+    for (int i = 0; i < columnNames.size(); i++)
+    {
+      builder.append(", ?"); //$NON-NLS-1$
+    }
+
+    builder.append(")"); //$NON-NLS-1$
+    sqlInsert = builder.toString();
+
+    // ----------------- remove current entry -----------------
+    builder = new StringBuilder("UPDATE "); //$NON-NLS-1$
+    builder.append(tableName);
+    builder.append(" SET "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_VERSION_REMOVED);
+    builder.append("=? "); //$NON-NLS-1$
+    builder.append(" WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_REVISION_ID);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_BRANCH);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_IDX);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_VERSION_REMOVED);
+    builder.append(" IS NULL"); //$NON-NLS-1$
+    sqlRemoveEntry = builder.toString();
+
+    // ----------------- delete temporary entry -----------------
+    builder = new StringBuilder("DELETE FROM "); //$NON-NLS-1$
+    builder.append(tableName);
+    builder.append(" WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_REVISION_ID);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_BRANCH);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_IDX);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_VERSION_ADDED);
+    builder.append("=?"); //$NON-NLS-1$
+    sqlDeleteEntry = builder.toString();
+
+    // ----------------- update index -----------------
+    builder = new StringBuilder("UPDATE "); //$NON-NLS-1$
+    builder.append(tableName);
+    builder.append(" SET "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_IDX);
+    builder.append("=? WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_REVISION_ID);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_BRANCH);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_VERSION_ADDED);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_IDX);
+    builder.append("=?"); //$NON-NLS-1$
+    sqlUpdateIndex = builder.toString();
+
+    // ----------------- get current value -----------------
+    builder = new StringBuilder("SELECT "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_TAG);
+    builder.append(", "); //$NON-NLS-1$
+
+    iter = columnNames.iterator();
+    while (iter.hasNext())
+    {
+      builder.append(iter.next());
+      if (iter.hasNext())
+      {
+        builder.append(", "); //$NON-NLS-1$
+      }
+    }
+
+    builder.append(" FROM "); //$NON-NLS-1$
+    builder.append(tableName);
+    builder.append(" WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_REVISION_ID);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_BRANCH);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_IDX);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_VERSION_REMOVED);
+    builder.append(" IS NULL"); //$NON-NLS-1$
+    sqlGetValue = builder.toString();
+
+    // ----------- clear list items -------------------------
+    builder = new StringBuilder("UPDATE "); //$NON-NLS-1$
+    builder.append(tableName);
+    builder.append(" SET "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_VERSION_REMOVED);
+    builder.append("=? "); //$NON-NLS-1$
+    builder.append(" WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_REVISION_ID);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_BRANCH);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_VERSION_REMOVED);
+    builder.append(" IS NULL"); //$NON-NLS-1$
+    sqlClearList = builder.toString();
+  }
+
+  protected List<DBType> getDBTypes()
+  {
+    return dbTypes;
+  }
+
+  protected final IDBTable getTable()
+  {
+    return table;
+  }
+
+  protected final List<String> getColumnNames()
+  {
+    return columnNames;
+  }
+
+  protected final Map<CDOID, ITypeMapping> getTypeMappings()
+  {
+    return typeMappings;
+  }
+
+  protected final Map<CDOID, String> getTagMap()
+  {
+    return tagMap;
+  }
+
+  public void readValues(IDBStoreAccessor accessor, InternalCDORevision revision, int listChunk)
+  {
+    MoveableList<Object> list = revision.getList(getFeature());
+    int valuesToRead = list.size();
+
+    if (listChunk != CDORevision.UNCHUNKED && listChunk < valuesToRead)
+    {
+      valuesToRead = listChunk;
+    }
+
+    if (valuesToRead == 0)
+    {
+      // nothing to read take shortcut
+      return;
+    }
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Reading list values for feature {0}.{1} of {2}", getContainingClass().getName(), getFeature() //$NON-NLS-1$
+          .getName(), revision);
+    }
+
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+    ResultSet resultSet = null;
+
+    IStoreChunkReader baseReader = null;
+
+    try
+    {
+      String sql = sqlSelectChunksPrefix + sqlOrderByIndex;
+
+      CDOID id = revision.getID();
+      int branchID = revision.getBranch().getID();
+
+      stmt = statementCache.getPreparedStatement(sql, ReuseProbability.HIGH);
+      idHandler.setCDOID(stmt, 1, id);
+      stmt.setInt(2, branchID);
+      stmt.setInt(3, revision.getVersion());
+      stmt.setInt(4, revision.getVersion());
+
+      stmt.setMaxRows(valuesToRead); // optimization - don't read unneeded rows.
+
+      resultSet = stmt.executeQuery();
+
+      int currentIndex = 0;
+
+      while (valuesToRead > 0 && resultSet.next())
+      {
+        int index = resultSet.getInt(1);
+        if (index > currentIndex)
+        {
+          if (baseReader == null)
+          {
+            baseReader = createBaseChunkReader(accessor, id, branchID);
+          }
+
+          baseReader.addRangedChunk(currentIndex, index);
+          if (TRACER.isEnabled())
+          {
+            TRACER.format("Scheduling range {0}-{1} to be read from base revision", currentIndex, index); //$NON-NLS-1$
+          }
+
+          valuesToRead -= index - currentIndex;
+          currentIndex = index;
+        }
+
+        CDOID tag = idHandler.getCDOID(resultSet, 2);
+        Object value = getTypeMapping(tag).readValue(resultSet);
+        if (TRACER.isEnabled())
+        {
+          TRACER.format("Read value for index {0} from result set: {1}", currentIndex, value); //$NON-NLS-1$
+        }
+
+        list.set(currentIndex++, CDORevisionUtil.createFeatureMapEntry(getFeatureByTag(tag), value));
+        valuesToRead--;
+      }
+
+      if (valuesToRead > 0)
+      {
+        if (baseReader == null)
+        {
+          baseReader = createBaseChunkReader(accessor, id, branchID);
+        }
+
+        baseReader.addRangedChunk(currentIndex, currentIndex + valuesToRead);
+      }
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex);
+    }
+    finally
+    {
+      DBUtil.close(resultSet);
+      statementCache.releasePreparedStatement(stmt);
+    }
+
+    if (baseReader != null)
+    {
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Reading base revision chunks for featureMap {0}.{1} of {2} from base revision {3}", //$NON-NLS-1$
+            getContainingClass().getName(), getFeature().getName(), revision, baseReader.getRevision());
+      }
+
+      List<Chunk> baseChunks = baseReader.executeRead();
+      for (Chunk chunk : baseChunks)
+      {
+        int startIndex = chunk.getStartIndex();
+        for (int i = 0; i < chunk.size(); i++)
+        {
+          list.set(startIndex + i, chunk.get(i));
+        }
+      }
+    }
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Reading list values done for feature {0}.{1} of {2}", getContainingClass().getName(), //$NON-NLS-1$
+          getFeature().getName(), revision);
+    }
+  }
+
+  private void addFeature(CDOID tag)
+  {
+    EStructuralFeature modelFeature = getFeatureByTag(tag);
+
+    ITypeMapping typeMapping = getMappingStrategy().createValueMapping(modelFeature);
+    String column = CDODBSchema.FEATUREMAP_VALUE + "_" + typeMapping.getDBType(); //$NON-NLS-1$
+
+    tagMap.put(tag, column);
+    typeMapping.setDBField(table, column);
+    typeMappings.put(tag, typeMapping);
+  }
+
+  public final void readChunks(IDBStoreChunkReader chunkReader, List<Chunk> chunks, String where)
+  {
+    CDORevision revision = chunkReader.getRevision();
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Reading list chunk values for feature {0}.{1} of {2}", getContainingClass().getName(), //$NON-NLS-1$
+          getFeature().getName(), revision);
+    }
+
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = chunkReader.getAccessor().getStatementCache();
+    PreparedStatement stmt = null;
+    ResultSet resultSet = null;
+
+    IStoreChunkReader baseReader = null;
+
+    try
+    {
+      StringBuilder builder = new StringBuilder(sqlSelectChunksPrefix);
+      if (where != null)
+      {
+        builder.append(" AND "); //$NON-NLS-1$
+        builder.append(where);
+      }
+
+      builder.append(sqlOrderByIndex);
+
+      String sql = builder.toString();
+      stmt = statementCache.getPreparedStatement(sql, ReuseProbability.LOW);
+      idHandler.setCDOID(stmt, 1, revision.getID());
+      stmt.setInt(2, revision.getBranch().getID());
+      stmt.setInt(3, revision.getVersion());
+      stmt.setInt(4, revision.getVersion());
+
+      resultSet = stmt.executeQuery();
+
+      int nextDBIndex = Integer.MAX_VALUE; // next available DB index
+      if (resultSet.next())
+      {
+        nextDBIndex = resultSet.getInt(1);
+      }
+
+      for (Chunk chunk : chunks)
+      {
+        int startIndex = chunk.getStartIndex();
+        int missingValueStartIndex = -1;
+
+        for (int i = 0; i < chunk.size(); i++)
+        {
+          int nextListIndex = startIndex + i; // next expected list index
+
+          if (nextDBIndex == nextListIndex)
+          {
+            // DB value is available. check first if missing indexes were present before.
+            if (missingValueStartIndex != -1)
+            {
+              // read missing indexes from missingValueStartIndex to currentIndex
+              if (baseReader == null)
+              {
+                baseReader = createBaseChunkReader(chunkReader.getAccessor(), chunkReader.getRevision().getID(),
+                    chunkReader.getRevision().getBranch().getID());
+              }
+
+              if (TRACER.isEnabled())
+              {
+                TRACER.format(
+                    "Scheduling range {0}-{1} to be read from base revision", missingValueStartIndex, nextListIndex); //$NON-NLS-1$
+              }
+
+              baseReader.addRangedChunk(missingValueStartIndex, nextListIndex);
+
+              // reset missingValueStartIndex
+              missingValueStartIndex = -1;
+            }
+
+            // now read value and set to chunk
+            CDOID tag = idHandler.getCDOID(resultSet, 2);
+            Object value = getTypeMapping(tag).readValue(resultSet);
+            if (TRACER.isEnabled())
+            {
+              TRACER.format("ChunkReader read value for index {0} from result set: {1}", nextDBIndex, value); //$NON-NLS-1$
+            }
+
+            chunk.add(i, CDORevisionUtil.createFeatureMapEntry(getFeatureByTag(tag), value));
+
+            // advance DB cursor and read next available index
+            if (resultSet.next())
+            {
+              nextDBIndex = resultSet.getInt(1);
+            }
+            else
+            {
+              // no more DB indexes available, but we have to continue checking for gaps, therefore set to MAX_VALUE
+              nextDBIndex = Integer.MAX_VALUE;
+            }
+          }
+          else
+          {
+            // gap between next DB index and next list index detected.
+            // skip until end of chunk or until DB value becomes available
+            if (missingValueStartIndex == -1)
+            {
+              missingValueStartIndex = nextListIndex;
+            }
+          }
+        }
+
+        // chunk complete. check for missing values at the end of the chunk.
+        if (missingValueStartIndex != -1)
+        {
+          // read missing indexes from missingValueStartIndex to last chunk index
+          if (baseReader == null)
+          {
+            baseReader = createBaseChunkReader(chunkReader.getAccessor(), chunkReader.getRevision().getID(),
+                chunkReader.getRevision().getBranch().getID());
+          }
+          baseReader.addRangedChunk(missingValueStartIndex, chunk.getStartIndex() + chunk.size());
+        }
+      }
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex);
+    }
+    finally
+    {
+      DBUtil.close(resultSet);
+      statementCache.releasePreparedStatement(stmt);
+    }
+
+    // now read missing values from base revision.
+    if (baseReader != null)
+    {
+      List<Chunk> baseChunks = baseReader.executeRead();
+
+      Iterator<Chunk> thisIterator = chunks.iterator();
+      Chunk thisChunk = thisIterator.next();
+
+      for (Chunk baseChunk : baseChunks)
+      {
+        int baseStartIndex = baseChunk.getStartIndex();
+
+        while (baseStartIndex > thisChunk.getStartIndex() + thisChunk.size())
+        {
+          // advance thisChunk, because it does not match baseChunk
+          thisChunk = thisIterator.next();
+        }
+
+        // baseChunk now corresponds to this chunk, but startIndex of baseChunk may be higher.
+        // therefore calculate offset
+        int offset = thisChunk.getStartIndex() - baseStartIndex;
+
+        // and copy values.
+        for (int i = 0; i < baseChunk.size(); i++)
+        {
+          thisChunk.add(i + offset, baseChunk.get(i));
+        }
+      } // finally, continue with the next baseChunk
+
+    }
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Reading list chunk values done for feature {0}.{1} of {2}", getContainingClass().getName(), //$NON-NLS-1$
+          getFeature(), revision);
+    }
+  }
+
+  public void writeValues(IDBStoreAccessor accessor, InternalCDORevision revision)
+  {
+    CDOList values = revision.getList(getFeature());
+
+    int idx = 0;
+    for (Object element : values)
+    {
+      writeValue(accessor, revision, idx++, element);
+    }
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Writing done"); //$NON-NLS-1$
+    }
+  }
+
+  protected final void writeValue(IDBStoreAccessor accessor, CDORevision revision, int idx, Object value)
+  {
+    if (TRACER.isEnabled())
+    {
+      TRACER
+          .format(
+              "Writing value for feature {0}.{1} index {2} of {3} : {4}", getContainingClass().getName(), getFeature(), idx, revision, value); //$NON-NLS-1$
+    }
+
+    addEntry(accessor, revision.getID(), revision.getBranch().getID(), revision.getVersion(), idx, value,
+        revision.getTimeStamp());
+  }
+
+  /**
+   * Get column name (lazy).
+   * 
+   * @param tag
+   *          The feature's MetaID in CDO
+   * @return the column name where the values are stored
+   */
+  protected String getColumnName(CDOID tag)
+  {
+    String column = tagMap.get(tag);
+    if (column == null)
+    {
+      addFeature(tag);
+      column = tagMap.get(tag);
+    }
+
+    return column;
+  }
+
+  /**
+   * Get type mapping (lazy).
+   * 
+   * @param tag
+   *          The feature's MetaID in CDO
+   * @return the corresponding type mapping
+   */
+  protected ITypeMapping getTypeMapping(CDOID tag)
+  {
+    ITypeMapping typeMapping = typeMappings.get(tag);
+    if (typeMapping == null)
+    {
+      addFeature(tag);
+      typeMapping = typeMappings.get(tag);
+    }
+
+    return typeMapping;
+  }
+
+  /**
+   * @param metaID
+   * @return the column name where the values are stored
+   */
+  private EStructuralFeature getFeatureByTag(CDOID tag)
+  {
+    return (EStructuralFeature)getMappingStrategy().getStore().getMetaDataManager().getMetaInstance(tag);
+  }
+
+  /**
+   * @param feature
+   *          The EStructuralFeature
+   * @return The feature's MetaID in CDO
+   */
+  protected CDOID getTagByFeature(EStructuralFeature feature, long created)
+  {
+    return getMappingStrategy().getStore().getMetaDataManager().getMetaID(feature, created);
+  }
+
+  /**
+   * Clear a list of a given revision.
+   * 
+   * @param accessor
+   *          the accessor to use
+   * @param id
+   *          the id of the revision from which to remove all items
+   */
+  public void clearList(IDBStoreAccessor accessor, CDOID id, int branchId, int oldVersion, int newVersion,
+      int lastIndex, long timestamp)
+  {
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmtDeleteTemp = null;
+    PreparedStatement stmtClear = null;
+
+    try
+    {
+      // check for each index if the value exists in the current branch
+      for (int i = 0; i <= lastIndex; i++)
+      {
+        if (getValue(accessor, id, branchId, i, false) == null)
+        {
+          // if not, add a historic entry for missing ones.
+          addHistoricEntry(accessor, id, branchId, 0, newVersion, i, getValueFromBase(accessor, id, branchId, i),
+              timestamp);
+        }
+      }
+
+      // clear rest of the list
+      stmtClear = statementCache.getPreparedStatement(sqlClearList, ReuseProbability.HIGH);
+      stmtClear.setInt(1, newVersion);
+      idHandler.setCDOID(stmtClear, 2, id);
+      stmtClear.setInt(3, branchId);
+
+      int result = DBUtil.update(stmtClear, false);
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("ClearList result: {0}", result); //$NON-NLS-1$
+      }
+    }
+    catch (SQLException e)
+    {
+      throw new DBException(e);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmtDeleteTemp);
+      statementCache.releasePreparedStatement(stmtClear);
+    }
+  }
+
+  public void objectDetached(IDBStoreAccessor accessor, CDOID id, long revised)
+  {
+    InternalCDORevision revision = (InternalCDORevision)accessor.getTransaction().getRevision(id);
+    int branchId = accessor.getTransaction().getBranch().getID();
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("objectDetached {1}", revision); //$NON-NLS-1$
+    }
+
+    clearList(accessor, id, branchId, revision.getVersion(), FINAL_VERSION, revision.getList(getFeature()).size() - 1,
+        revised);
+  }
+
+  public void processDelta(final IDBStoreAccessor accessor, final CDOID id, final int branchId, int oldVersion,
+      final int newVersion, long created, CDOListFeatureDelta delta)
+  {
+    List<CDOFeatureDelta> listChanges = delta.getListChanges();
+    if (listChanges.size() == 0)
+    {
+      // nothing to do.
+      return;
+    }
+
+    InternalCDORevision originalRevision = (InternalCDORevision)accessor.getTransaction().getRevision(id);
+    int oldListSize = originalRevision.getList(getFeature()).size();
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("ListTableMapping.processDelta for revision {0} - previous list size: {1}", originalRevision, //$NON-NLS-1$
+          oldListSize);
+    }
+
+    // let the visitor collect the changes
+    ListDeltaVisitor visitor = new ListDeltaVisitor(accessor, originalRevision, branchId, oldVersion, newVersion,
+        created);
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Processing deltas..."); //$NON-NLS-1$
+    }
+
+    // optimization: it's only necessary to process deltas
+    // starting with the last feature delta which clears the list
+    // (any operation before the clear is cascaded by it anyway)
+    int index = listChanges.size() - 1;
+    while (index > 0)
+    {
+      CDOFeatureDelta listDelta = listChanges.get(index);
+      if (listDelta instanceof CDOClearFeatureDelta || listDelta instanceof CDOUnsetFeatureDelta)
+      {
+        break;
+      }
+      index--;
+    }
+    while (index < listChanges.size())
+    {
+      listChanges.get(index++).accept(visitor);
+    }
+  }
+
+  private class ListDeltaVisitor implements CDOFeatureDeltaVisitor
+  {
+    private IDBStoreAccessor accessor;
+
+    private InternalCDORevision originalRevision;
+
+    private CDOID id;
+
+    private int branchID;
+
+    private int oldVersion;
+
+    private int newVersion;
+
+    private int lastIndex;
+
+    private long timestamp;
+
+    public ListDeltaVisitor(IDBStoreAccessor accessor, InternalCDORevision originalRevision, int targetBranchID,
+        int oldVersion, int newVersion, long timestamp)
+    {
+      this.accessor = accessor;
+      this.originalRevision = originalRevision;
+      id = this.originalRevision.getID();
+      branchID = targetBranchID;
+      this.oldVersion = oldVersion;
+      this.newVersion = newVersion;
+      lastIndex = originalRevision.getList(getFeature()).size() - 1;
+      this.timestamp = timestamp;
+    }
+
+    public void visit(CDOMoveFeatureDelta delta)
+    {
+      int fromIdx = delta.getOldPosition();
+      int toIdx = delta.getNewPosition();
+
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Delta Moving: {0} to {1}", fromIdx, toIdx); //$NON-NLS-1$
+      }
+
+      Object value = getValue(accessor, id, branchID, fromIdx, true);
+
+      // remove the item
+      removeEntry(accessor, id, branchID, oldVersion, newVersion, fromIdx, timestamp);
+
+      // adjust indexes and shift either up or down
+      if (fromIdx < toIdx)
+      {
+        moveOneUp(accessor, id, branchID, oldVersion, newVersion, fromIdx + 1, toIdx);
+      }
+      else
+      { // fromIdx > toIdx here
+        moveOneDown(accessor, id, branchID, oldVersion, newVersion, toIdx, fromIdx - 1);
+      }
+
+      // create the item
+      addEntry(accessor, id, branchID, newVersion, toIdx, value, timestamp);
+    }
+
+    public void visit(CDOAddFeatureDelta delta)
+    {
+      int startIndex = delta.getIndex();
+      int endIndex = lastIndex;
+
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Delta Adding at: {0}", startIndex); //$NON-NLS-1$
+      }
+
+      if (startIndex <= endIndex)
+      {
+        // make room for the new item
+        moveOneDown(accessor, id, branchID, oldVersion, newVersion, startIndex, endIndex);
+      }
+
+      // create the item
+      addEntry(accessor, id, branchID, newVersion, startIndex, delta.getValue(), timestamp);
+
+      ++lastIndex;
+    }
+
+    public void visit(CDORemoveFeatureDelta delta)
+    {
+      int startIndex = delta.getIndex();
+      int endIndex = lastIndex;
+
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Delta Removing at: {0}", startIndex); //$NON-NLS-1$
+      }
+
+      // remove the item
+      removeEntry(accessor, id, branchID, oldVersion, newVersion, startIndex, timestamp);
+
+      // make room for the new item
+      moveOneUp(accessor, id, branchID, oldVersion, newVersion, startIndex + 1, endIndex);
+
+      --lastIndex;
+    }
+
+    public void visit(CDOSetFeatureDelta delta)
+    {
+      int index = delta.getIndex();
+
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Delta Setting at: {0}", index); //$NON-NLS-1$
+      }
+
+      // remove the item
+      removeEntry(accessor, id, branchID, oldVersion, newVersion, index, timestamp);
+
+      // create the item
+      addEntry(accessor, id, branchID, newVersion, index, delta.getValue(), timestamp);
+    }
+
+    public void visit(CDOUnsetFeatureDelta delta)
+    {
+      if (delta.getFeature().isUnsettable())
+      {
+        throw new ImplementationError("Should not be called"); //$NON-NLS-1$
+      }
+
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Delta Unsetting"); //$NON-NLS-1$
+      }
+
+      clearList(accessor, id, branchID, oldVersion, newVersion, lastIndex, timestamp);
+      lastIndex = -1;
+    }
+
+    public void visit(CDOListFeatureDelta delta)
+    {
+      throw new ImplementationError("Should not be called"); //$NON-NLS-1$
+    }
+
+    public void visit(CDOClearFeatureDelta delta)
+    {
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Delta Clearing"); //$NON-NLS-1$
+      }
+
+      clearList(accessor, id, branchID, oldVersion, newVersion, lastIndex, timestamp);
+      lastIndex = -1;
+    }
+
+    public void visit(CDOContainerFeatureDelta delta)
+    {
+      throw new ImplementationError("Should not be called"); //$NON-NLS-1$
+    }
+
+    private void moveOneUp(IDBStoreAccessor accessor, CDOID id, int branchId, int oldVersion, int newVersion,
+        int startIndex, int endIndex)
+    {
+      IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+      IPreparedStatementCache statementCache = accessor.getStatementCache();
+      PreparedStatement stmt = null;
+
+      try
+      {
+        stmt = statementCache.getPreparedStatement(sqlUpdateIndex, ReuseProbability.HIGH);
+
+        for (int index = startIndex; index <= endIndex; ++index)
+        {
+          if (TRACER.isEnabled())
+          {
+            TRACER.format("moveOneUp moving: {0} -> {1}", index, index - 1); //$NON-NLS-1$
+          }
+
+          int column = 1;
+          stmt.setInt(column++, index - 1);
+          idHandler.setCDOID(stmt, startIndex++, id);
+          stmt.setInt(column++, branchId);
+          stmt.setInt(column++, newVersion);
+          stmt.setInt(column++, index);
+
+          int result = DBUtil.update(stmt, false);
+          switch (result)
+          {
+          case 1:
+            // entry for current revision was already present.
+            // index update succeeded.
+            if (TRACER.isEnabled())
+            {
+              TRACER.format("moveOneUp updated: {0} -> {1}", index, index - 1); //$NON-NLS-1$
+            }
+
+            break;
+          case 0:
+            Object value = getValue(accessor, id, branchId, index, false);
+
+            if (value != null)
+            {
+              if (TRACER.isEnabled())
+              {
+                TRACER.format("moveOneUp remove: {0}", index); //$NON-NLS-1$
+              }
+
+              removeEntry(accessor, id, branchId, oldVersion, newVersion, index, timestamp);
+            }
+            else
+            {
+              value = getValueFromBase(accessor, id, branchId, index);
+              {
+                TRACER.format("moveOneUp add historic entry at: {0}", index); //$NON-NLS-1$
+              }
+
+              addHistoricEntry(accessor, id, branchId, 0, newVersion, index, value, timestamp);
+            }
+
+            if (TRACER.isEnabled())
+            {
+              TRACER.format("moveOneUp add: {0}", index - 1); //$NON-NLS-1$
+            }
+
+            addEntry(accessor, id, branchId, newVersion, index - 1, value, timestamp);
+            break;
+          default:
+            if (TRACER.isEnabled())
+            {
+              TRACER.format("moveOneUp Too many results: {0} -> {1}: {2}", index, index + 1, result); //$NON-NLS-1$
+            }
+
+            throw new DBException("Too many results"); //$NON-NLS-1$
+          }
+        }
+      }
+      catch (SQLException e)
+      {
+        throw new DBException(e);
+      }
+      finally
+      {
+        statementCache.releasePreparedStatement(stmt);
+      }
+    }
+
+    private void moveOneDown(IDBStoreAccessor accessor, CDOID id, int branchId, int oldVersion, int newVersion,
+        int startIndex, int endIndex)
+    {
+      IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+      IPreparedStatementCache statementCache = accessor.getStatementCache();
+      PreparedStatement stmt = null;
+
+      try
+      {
+        stmt = statementCache.getPreparedStatement(sqlUpdateIndex, ReuseProbability.HIGH);
+        for (int index = endIndex; index >= startIndex; --index)
+        {
+          if (TRACER.isEnabled())
+          {
+            TRACER.format("moveOneDown moving: {0} -> {1}", index, index + 1); //$NON-NLS-1$
+          }
+
+          int column = 1;
+          stmt.setInt(column++, index + 1);
+          idHandler.setCDOID(stmt, column++, id);
+          stmt.setInt(column++, branchId);
+          stmt.setInt(column++, newVersion);
+          stmt.setInt(column++, index);
+
+          int result = DBUtil.update(stmt, false);
+          switch (result)
+          {
+          case 1:
+            // entry for current revision was already present.
+            // index update succeeded.
+            if (TRACER.isEnabled())
+            {
+              TRACER.format("moveOneDown updated: {0} -> {1}", index, index + 1); //$NON-NLS-1$
+            }
+
+            break;
+          case 0:
+            Object value = getValue(accessor, id, branchId, index, false);
+            if (value != null)
+            {
+              if (TRACER.isEnabled())
+              {
+                TRACER.format("moveOneDown remove: {0}", index); //$NON-NLS-1$
+              }
+
+              removeEntry(accessor, id, branchId, oldVersion, newVersion, index, timestamp);
+            }
+            else
+            {
+              value = getValueFromBase(accessor, id, branchId, index);
+              {
+                TRACER.format("moveOneDown add historic entry at: {0}", index); //$NON-NLS-1$
+              }
+
+              addHistoricEntry(accessor, id, branchId, 0, newVersion, index, value, timestamp);
+            }
+
+            addEntry(accessor, id, branchId, newVersion, index + 1, value, timestamp);
+            break;
+          default:
+            if (TRACER.isEnabled())
+            {
+              TRACER.format("moveOneDown Too many results: {0} -> {1}: {2}", index, index + 1, result); //$NON-NLS-1$
+            }
+
+            throw new DBException("Too many results"); //$NON-NLS-1$
+          }
+        }
+      }
+      catch (SQLException e)
+      {
+        throw new DBException(e);
+      }
+      finally
+      {
+        statementCache.releasePreparedStatement(stmt);
+      }
+    }
+  }
+
+  private void addEntry(IDBStoreAccessor accessor, CDOID id, int branchId, int version, int index, Object value,
+      long timestamp)
+  {
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Adding value for feature() {0}.{1} index {2} of {3}v{4} : {5}", //$NON-NLS-1$
+          getContainingClass().getName(), getFeature().getName(), index, id, version, value);
+    }
+
+    try
+    {
+      FeatureMap.Entry entry = (FeatureMap.Entry)value;
+      EStructuralFeature entryFeature = entry.getEStructuralFeature();
+      CDOID tag = getTagByFeature(entryFeature, timestamp);
+      String columnName = getColumnName(tag);
+
+      stmt = statementCache.getPreparedStatement(sqlInsert, ReuseProbability.HIGH);
+
+      int column = 1;
+      idHandler.setCDOID(stmt, column++, id);
+      stmt.setInt(column++, branchId);
+      stmt.setInt(column++, version);
+      stmt.setNull(column++, DBType.INTEGER.getCode()); // versionRemoved
+      stmt.setInt(column++, index);
+      idHandler.setCDOID(stmt, column++, tag);
+
+      for (int i = 0; i < columnNames.size(); i++)
+      {
+        if (columnNames.get(i).equals(columnName))
+        {
+          getTypeMapping(tag).setValue(stmt, column++, entry.getValue());
+        }
+        else
+        {
+          stmt.setNull(column++, getDBTypes().get(i).getCode());
+        }
+      }
+
+      DBUtil.update(stmt, true);
+    }
+    catch (SQLException e)
+    {
+      throw new DBException(e);
+    }
+    catch (IllegalStateException e)
+    {
+      throw new DBException(e);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  private void addHistoricEntry(IDBStoreAccessor accessor, CDOID id, int branchId, int versionAdded,
+      int versionRemoved, int index, Object value, long timestamp)
+  {
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format(
+          "Adding historic value for feature {0}.{1} index {2} of {3}:{4}v{5}-v{6} : {7}", //$NON-NLS-1$
+          getContainingClass().getName(), getFeature().getName(), index, id, branchId, versionAdded, versionRemoved,
+          value);
+    }
+
+    try
+    {
+      FeatureMap.Entry entry = (FeatureMap.Entry)value;
+      EStructuralFeature entryFeature = entry.getEStructuralFeature();
+      CDOID tag = getTagByFeature(entryFeature, timestamp);
+      String columnName = getColumnName(tag);
+
+      stmt = statementCache.getPreparedStatement(sqlInsert, ReuseProbability.HIGH);
+
+      int column = 1;
+      idHandler.setCDOID(stmt, column++, id);
+      stmt.setInt(column++, branchId);
+      stmt.setInt(column++, versionAdded);
+      stmt.setNull(column++, versionRemoved);
+      stmt.setInt(column++, index);
+      idHandler.setCDOID(stmt, column++, tag);
+
+      for (int i = 0; i < columnNames.size(); i++)
+      {
+        if (columnNames.get(i).equals(columnName))
+        {
+          getTypeMapping(tag).setValue(stmt, column++, entry.getValue());
+        }
+        else
+        {
+          stmt.setNull(column++, getDBTypes().get(i).getCode());
+        }
+      }
+
+      DBUtil.update(stmt, true);
+    }
+    catch (SQLException e)
+    {
+      throw new DBException(e);
+    }
+    catch (IllegalStateException e)
+    {
+      throw new DBException(e);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  private void removeEntry(IDBStoreAccessor accessor, CDOID id, int branchId, int oldVersion, int newVersion,
+      int index, long timestamp)
+  {
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Removing value for feature() {0}.{1} index {2} of {3}v{4}", //$NON-NLS-1$
+          getContainingClass().getName(), getFeature().getName(), index, id, newVersion);
+    }
+
+    try
+    {
+      // try to delete a temporary entry first
+      stmt = statementCache.getPreparedStatement(sqlDeleteEntry, ReuseProbability.HIGH);
+
+      int column = 1;
+      idHandler.setCDOID(stmt, column++, id);
+      stmt.setInt(column++, branchId);
+      stmt.setInt(column++, index);
+      stmt.setInt(column++, newVersion);
+
+      int result = DBUtil.update(stmt, false);
+      if (result == 1)
+      {
+        if (TRACER.isEnabled())
+        {
+          TRACER.format("removeEntry deleted: {0}", index); //$NON-NLS-1$
+        }
+      }
+      else if (result > 1)
+      {
+        if (TRACER.isEnabled())
+        {
+          TRACER.format("removeEntry Too many results: {0}: {1}", index, result); //$NON-NLS-1$
+        }
+
+        throw new DBException("Too many results"); //$NON-NLS-1$
+      }
+      else
+      {
+        // no temporary entry found, so mark the entry as removed
+        statementCache.releasePreparedStatement(stmt);
+        stmt = statementCache.getPreparedStatement(sqlRemoveEntry, ReuseProbability.HIGH);
+
+        column = 1;
+        stmt.setInt(column++, newVersion);
+        idHandler.setCDOID(stmt, column++, id);
+        stmt.setInt(column++, branchId);
+        stmt.setInt(column++, index);
+        result = DBUtil.update(stmt, false);
+
+        if (result == 0)
+        {
+          // no entry removed -> this means that we are in a branch and
+          // the entry has not been modified since the branch fork.
+          // therefore, we have to copy the base value and mark it as removed
+          Object value = getValueFromBase(accessor, id, branchId, index);
+          addHistoricEntry(accessor, id, branchId, 0, newVersion, index, value, timestamp);
+        }
+      }
+    }
+    catch (SQLException e)
+    {
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Removing value for feature() {0}.{1} index {2} of {3}v{4} FAILED {5}", //$NON-NLS-1$
+            getContainingClass().getName(), getFeature().getName(), index, id, newVersion, e.getMessage());
+      }
+
+      throw new DBException(e);
+    }
+    catch (IllegalStateException e)
+    {
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Removing value for feature() {0}.{1} index {2} of {3}v{4} FAILED {5}", //$NON-NLS-1$
+            getContainingClass().getName(), getFeature().getName(), index, id, newVersion, e.getMessage());
+      }
+
+      throw new DBException(e);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  private FeatureMap.Entry getValue(IDBStoreAccessor accessor, CDOID id, int branchId, int index, boolean getFromBase)
+  {
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+    FeatureMap.Entry result = null;
+
+    try
+    {
+      stmt = statementCache.getPreparedStatement(sqlGetValue, ReuseProbability.HIGH);
+
+      int column = 1;
+      idHandler.setCDOID(stmt, column++, id);
+      stmt.setInt(column++, branchId);
+      stmt.setInt(column++, index);
+
+      ResultSet resultSet = stmt.executeQuery();
+      if (resultSet.next())
+      {
+        CDOID tag = idHandler.getCDOID(resultSet, 1);
+        Object value = getTypeMapping(tag).readValue(resultSet);
+        result = CDORevisionUtil.createFeatureMapEntry(getFeatureByTag(tag), value);
+      }
+      else
+      {
+        // value is not in this branch.
+        // -> read from base revision
+        if (getFromBase)
+        {
+          result = getValueFromBase(accessor, id, branchId, index);
+        } // else: result remains null
+      }
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Read value (index {0}) from result set: {1}", index, result); //$NON-NLS-1$
+      }
+    }
+    catch (SQLException e)
+    {
+      throw new DBException(e);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+
+    return result;
+  }
+
+  /**
+   * Read a single value (at a given index) from the base revision
+   * 
+   * @param accessor
+   *          the DBStoreAccessor
+   * @param id
+   *          the ID of the revision
+   * @param branchID
+   *          the ID of the current (child) branch
+   * @param index
+   *          the index to read the value from
+   * @return the value which is at index <code>index</code> in revision with ID <code>id</code> in the parent branch at
+   *         the base of this branch (indicated by <code>branchID</code>).
+   */
+  private FeatureMap.Entry getValueFromBase(IDBStoreAccessor accessor, CDOID id, int branchID, int index)
+  {
+    IStoreChunkReader chunkReader = createBaseChunkReader(accessor, id, branchID);
+    chunkReader.addSimpleChunk(index);
+    List<Chunk> chunks = chunkReader.executeRead();
+    return (FeatureMap.Entry)chunks.get(0).get(0);
+  }
+
+  private IStoreChunkReader createBaseChunkReader(IDBStoreAccessor accessor, CDOID id, int branchID)
+  {
+    CDOBranchPoint base = accessor.getStore().getRepository().getBranchManager().getBranch(branchID).getBase();
+    InternalCDORevision baseRevision = (InternalCDORevision)accessor.getStore().getRepository().getRevisionManager()
+        .getRevision(id, base, /* referenceChunk = */0, /* prefetchDepth = */CDORevision.DEPTH_NONE, true);
+    IStoreChunkReader chunkReader = accessor.createChunkReader(baseRevision, getFeature());
+    return chunkReader;
+  }
+
+  public final boolean queryXRefs(IDBStoreAccessor accessor, String mainTableName, String mainTableWhere,
+      QueryXRefsContext context, String idString)
+  {
+    // must never be called (a feature map is not associated with an EReference feature, so XRefs are nor supported
+    // here)
+    throw new ImplementationError("Should never be called!");
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/BranchingListTableMapping.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/BranchingListTableMapping.java
new file mode 100644
index 0000000..858c34a
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/BranchingListTableMapping.java
@@ -0,0 +1,71 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - 271444: [DB] Multiple refactorings bug 271444
+ *    Stefan Winkler - derived branch mapping from audit mapping
+ */
+package org.eclipse.emf.cdo.server.internal.db.mapping.horizontal;
+
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
+import org.eclipse.emf.cdo.server.db.mapping.IMappingStrategy;
+import org.eclipse.emf.cdo.server.internal.db.CDODBSchema;
+
+import org.eclipse.net4j.db.DBType;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+
+/**
+ * This is a list-table mapping for audit mode. It has ID and version columns and no delta support.
+ * 
+ * @author Eike Stepper
+ * @author Stefan Winkler
+ * @since 3.0
+ */
+public class BranchingListTableMapping extends AbstractListTableMapping
+{
+  private FieldInfo[] keyFields;
+
+  public BranchingListTableMapping(IMappingStrategy mappingStrategy, EClass eClass, EStructuralFeature feature)
+  {
+    super(mappingStrategy, eClass, feature);
+  }
+
+  @Override
+  protected FieldInfo[] getKeyFields()
+  {
+    if (keyFields == null)
+    {
+      keyFields = new FieldInfo[] {
+          new FieldInfo(CDODBSchema.LIST_REVISION_ID, getMappingStrategy().getStore().getIDHandler().getDBType()),
+          new FieldInfo(CDODBSchema.LIST_REVISION_BRANCH, DBType.INTEGER),
+          new FieldInfo(CDODBSchema.LIST_REVISION_VERSION, DBType.INTEGER) };
+    }
+
+    return keyFields;
+  }
+
+  @Override
+  protected void setKeyFields(PreparedStatement stmt, CDORevision revision) throws SQLException
+  {
+    getMappingStrategy().getStore().getIDHandler().setCDOID(stmt, 1, revision.getID());
+    stmt.setInt(2, revision.getBranch().getID());
+    stmt.setInt(3, revision.getVersion());
+  }
+
+  public void objectDetached(IDBStoreAccessor accessor, CDOID id, long revised)
+  {
+    // the audit list mapping does not care about revised references -> NOP
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/BranchingListTableMappingWithRanges.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/BranchingListTableMappingWithRanges.java
new file mode 100644
index 0000000..f7b056a
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/BranchingListTableMappingWithRanges.java
@@ -0,0 +1,1411 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * This class has been derived from AbstractListTableMapping
+ *
+ * Contributors:
+ *    Stefan Winkler - initial API and implementation taken from AuditListTableMappingWithRanges
+ *    Stefan Winkler - Bug 329025: [DB] Support branching for range-based mapping strategy
+ */
+package org.eclipse.emf.cdo.server.internal.db.mapping.horizontal;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.revision.CDOList;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.delta.CDOAddFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOClearFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOContainerFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDeltaVisitor;
+import org.eclipse.emf.cdo.common.revision.delta.CDOListFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOMoveFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDORemoveFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOSetFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOUnsetFeatureDelta;
+import org.eclipse.emf.cdo.server.IRepository;
+import org.eclipse.emf.cdo.server.IStoreAccessor.QueryXRefsContext;
+import org.eclipse.emf.cdo.server.IStoreChunkReader;
+import org.eclipse.emf.cdo.server.IStoreChunkReader.Chunk;
+import org.eclipse.emf.cdo.server.ITransaction;
+import org.eclipse.emf.cdo.server.db.IDBStore;
+import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
+import org.eclipse.emf.cdo.server.db.IDBStoreChunkReader;
+import org.eclipse.emf.cdo.server.db.IIDHandler;
+import org.eclipse.emf.cdo.server.db.IPreparedStatementCache;
+import org.eclipse.emf.cdo.server.db.IPreparedStatementCache.ReuseProbability;
+import org.eclipse.emf.cdo.server.db.mapping.IListMappingDeltaSupport;
+import org.eclipse.emf.cdo.server.db.mapping.IMappingStrategy;
+import org.eclipse.emf.cdo.server.db.mapping.ITypeMapping;
+import org.eclipse.emf.cdo.server.internal.db.CDODBSchema;
+import org.eclipse.emf.cdo.server.internal.db.bundle.OM;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+
+import org.eclipse.net4j.db.DBException;
+import org.eclipse.net4j.db.DBType;
+import org.eclipse.net4j.db.DBUtil;
+import org.eclipse.net4j.db.ddl.IDBField;
+import org.eclipse.net4j.db.ddl.IDBIndex.Type;
+import org.eclipse.net4j.db.ddl.IDBTable;
+import org.eclipse.net4j.util.ImplementationError;
+import org.eclipse.net4j.util.collection.MoveableList;
+import org.eclipse.net4j.util.om.trace.ContextTracer;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * This is a list-table mapping for audit mode. It is optimized for frequent insert operations at the list's end, which
+ * causes just 1 DB row to be changed. This is achieved by introducing a version range (columns cdo_version_added and
+ * cdo_version_removed) which records for which revisions a particular entry existed. Also, this mapping is mainly
+ * optimized for potentially very large lists: the need for having the complete list stored in memopy to do
+ * in-the-middle-moved and inserts is traded in for a few more DB access operations.
+ * 
+ * @author Eike Stepper
+ * @author Stefan Winkler
+ * @author Lothar Werzinger
+ */
+public class BranchingListTableMappingWithRanges extends BasicAbstractListTableMapping implements
+    IListMappingDeltaSupport
+{
+  private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG, BranchingListTableMappingWithRanges.class);
+
+  /**
+   * Used to clean up lists for detached objects.
+   */
+  private static final int FINAL_VERSION = Integer.MAX_VALUE;
+
+  /**
+   * The table of this mapping.
+   */
+  private IDBTable table;
+
+  /**
+   * The type mapping for the value field.
+   */
+  private ITypeMapping typeMapping;
+
+  // --------- SQL strings - see initSQLStrings() -----------------
+  private String sqlSelectChunksPrefix;
+
+  private String sqlOrderByIndex;
+
+  private String sqlInsertEntry;
+
+  private String sqlDeleteEntry;
+
+  private String sqlRemoveEntry;
+
+  private String sqlUpdateIndex;
+
+  private String sqlGetValue;
+
+  private String sqlClearList;
+
+  public BranchingListTableMappingWithRanges(IMappingStrategy mappingStrategy, EClass eClass, EStructuralFeature feature)
+  {
+    super(mappingStrategy, eClass, feature);
+    initTable();
+    initSQLStrings();
+  }
+
+  private void initTable()
+  {
+    IDBStore store = getMappingStrategy().getStore();
+    String tableName = getMappingStrategy().getTableName(getContainingClass(), getFeature());
+    table = store.getDBSchema().addTable(tableName);
+
+    IDBField[] dbFields = new IDBField[5];
+
+    dbFields[0] = table.addField(CDODBSchema.LIST_REVISION_ID, store.getIDHandler().getDBType());
+    dbFields[1] = table.addField(CDODBSchema.LIST_REVISION_BRANCH, DBType.INTEGER);
+    dbFields[2] = table.addField(CDODBSchema.LIST_REVISION_VERSION_ADDED, DBType.INTEGER);
+    dbFields[3] = table.addField(CDODBSchema.LIST_REVISION_VERSION_REMOVED, DBType.INTEGER);
+    dbFields[4] = table.addField(CDODBSchema.LIST_IDX, DBType.INTEGER);
+
+    // add field for value
+    typeMapping = getMappingStrategy().createValueMapping(getFeature());
+    typeMapping.createDBField(table, CDODBSchema.LIST_VALUE);
+
+    // add table indexes
+    for (IDBField dbField : dbFields)
+    {
+      table.addIndex(Type.NON_UNIQUE, dbField);
+    }
+  }
+
+  public Collection<IDBTable> getDBTables()
+  {
+    return Arrays.asList(table);
+  }
+
+  private void initSQLStrings()
+  {
+    String tableName = getTable().getName();
+
+    // ---------------- read chunks ----------------------------
+    StringBuilder builder = new StringBuilder();
+    builder.append("SELECT "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_IDX);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_VALUE);
+    builder.append(" FROM "); //$NON-NLS-1$
+    builder.append(tableName);
+    builder.append(" WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_ID);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_BRANCH);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_VERSION_ADDED);
+    builder.append("<=? AND ("); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_VERSION_REMOVED);
+    builder.append(" IS NULL OR "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_VERSION_REMOVED);
+    builder.append(">?)"); //$NON-NLS-1$
+    sqlSelectChunksPrefix = builder.toString();
+
+    sqlOrderByIndex = " ORDER BY " + CDODBSchema.LIST_IDX; //$NON-NLS-1$
+
+    // ----------------- insert entry -----------------
+    builder = new StringBuilder("INSERT INTO "); //$NON-NLS-1$
+    builder.append(tableName);
+    builder.append("("); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_ID);
+    builder.append(","); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_BRANCH);
+    builder.append(","); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_VERSION_ADDED);
+    builder.append(","); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_VERSION_REMOVED);
+    builder.append(","); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_IDX);
+    builder.append(","); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_VALUE);
+    builder.append(") VALUES (?, ?, ?, ?, ?, ?)"); //$NON-NLS-1$
+    sqlInsertEntry = builder.toString();
+
+    // ----------------- remove current entry -----------------
+    builder = new StringBuilder("UPDATE "); //$NON-NLS-1$
+    builder.append(getTable());
+    builder.append(" SET "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_VERSION_REMOVED);
+    builder.append("=? "); //$NON-NLS-1$
+    builder.append(" WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_ID);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_BRANCH);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_IDX);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_VERSION_REMOVED);
+    builder.append(" IS NULL"); //$NON-NLS-1$
+    sqlRemoveEntry = builder.toString();
+
+    // ----------------- delete temporary entry -----------------
+    builder = new StringBuilder("DELETE FROM "); //$NON-NLS-1$
+    builder.append(getTable());
+    builder.append(" WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_ID);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_BRANCH);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_IDX);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_VERSION_ADDED);
+    builder.append("=?"); //$NON-NLS-1$
+    sqlDeleteEntry = builder.toString();
+
+    // ----------------- update index -----------------
+    builder = new StringBuilder("UPDATE "); //$NON-NLS-1$
+    builder.append(getTable());
+    builder.append(" SET "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_IDX);
+    builder.append("=? WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_ID);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_BRANCH);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_VERSION_ADDED);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_IDX);
+    builder.append("=?"); //$NON-NLS-1$
+    sqlUpdateIndex = builder.toString();
+
+    // ----------------- get current value -----------------
+    builder = new StringBuilder("SELECT "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_VALUE);
+    builder.append(" FROM "); //$NON-NLS-1$
+    builder.append(getTable());
+    builder.append(" WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_ID);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_BRANCH);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_IDX);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_VERSION_REMOVED);
+    builder.append(" IS NULL"); //$NON-NLS-1$
+    sqlGetValue = builder.toString();
+
+    // ----------- clear list items -------------------------
+    builder = new StringBuilder("UPDATE "); //$NON-NLS-1$
+    builder.append(getTable());
+    builder.append(" SET "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_VERSION_REMOVED);
+    builder.append("=? "); //$NON-NLS-1$
+    builder.append(" WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_ID);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_BRANCH);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_VERSION_REMOVED);
+    builder.append(" IS NULL"); //$NON-NLS-1$
+    sqlClearList = builder.toString();
+  }
+
+  protected final IDBTable getTable()
+  {
+    return table;
+  }
+
+  protected final ITypeMapping getTypeMapping()
+  {
+    return typeMapping;
+  }
+
+  public void readValues(IDBStoreAccessor accessor, InternalCDORevision revision, final int listChunk)
+  {
+    MoveableList<Object> list = revision.getList(getFeature());
+    int valuesToRead = list.size();
+    if (listChunk != CDORevision.UNCHUNKED && listChunk < valuesToRead)
+    {
+      valuesToRead = listChunk;
+    }
+
+    if (valuesToRead == 0)
+    {
+      // nothing to read take shortcut
+      return;
+    }
+
+    CDOID id = revision.getID();
+    int branchID = revision.getBranch().getID();
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Reading list values for feature {0}.{1} of {2}", getContainingClass().getName(), //$NON-NLS-1$
+          getFeature().getName(), revision);
+    }
+
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+    ResultSet resultSet = null;
+
+    IStoreChunkReader baseReader = null;
+    try
+    {
+      String sql = sqlSelectChunksPrefix + sqlOrderByIndex;
+      stmt = statementCache.getPreparedStatement(sql, ReuseProbability.HIGH);
+      idHandler.setCDOID(stmt, 1, id);
+      stmt.setInt(2, branchID);
+      stmt.setInt(3, revision.getVersion());
+      stmt.setInt(4, revision.getVersion());
+      stmt.setMaxRows(valuesToRead); // optimization - don't read unneeded rows.
+
+      resultSet = stmt.executeQuery();
+
+      int currentIndex = 0;
+
+      while (valuesToRead > 0 && resultSet.next())
+      {
+        int index = resultSet.getInt(1);
+        if (index > currentIndex)
+        {
+          if (baseReader == null)
+          {
+            baseReader = createBaseChunkReader(accessor, id, branchID);
+          }
+
+          baseReader.addRangedChunk(currentIndex, index);
+          if (TRACER.isEnabled())
+          {
+            TRACER.format("Scheduling range {0}-{1} to be read from base revision", currentIndex, index); //$NON-NLS-1$
+          }
+
+          valuesToRead -= index - currentIndex;
+          currentIndex = index;
+        }
+
+        Object value = typeMapping.readValue(resultSet);
+        if (TRACER.isEnabled())
+        {
+          TRACER.format("Read value for index {0} from result set: {1}", currentIndex, value); //$NON-NLS-1$
+        }
+
+        list.set(currentIndex++, value);
+        valuesToRead--;
+      }
+
+      if (valuesToRead > 0)
+      {
+        if (baseReader == null)
+        {
+          baseReader = createBaseChunkReader(accessor, id, branchID);
+        }
+
+        baseReader.addRangedChunk(currentIndex, currentIndex + valuesToRead);
+        if (TRACER.isEnabled())
+        {
+          TRACER.format(
+              "Scheduling range {0}-{1} to be read from base revision", currentIndex, currentIndex + valuesToRead); //$NON-NLS-1$
+        }
+      }
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex);
+    }
+    finally
+    {
+      DBUtil.close(resultSet);
+      statementCache.releasePreparedStatement(stmt);
+    }
+
+    if (baseReader != null)
+    {
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Reading base revision chunks for feature {0}.{1} of {2} from base revision {3}", //$NON-NLS-1$
+            getContainingClass().getName(), getFeature().getName(), revision, baseReader.getRevision());
+      }
+
+      List<Chunk> baseChunks = baseReader.executeRead();
+      for (Chunk chunk : baseChunks)
+      {
+        int startIndex = chunk.getStartIndex();
+        for (int i = 0; i < chunk.size(); i++)
+        {
+          if (TRACER.isEnabled())
+          {
+            TRACER.format("Copying value {0} at chunk index {1}+{2} to index {3}", //$NON-NLS-1$
+                chunk.get(i), startIndex, i, startIndex + i);
+          }
+
+          list.set(startIndex + i, chunk.get(i));
+        }
+      }
+    }
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Reading {3} list values done for feature {0}.{1} of {2}", //$NON-NLS-1$
+          getContainingClass().getName(), getFeature().getName(), revision, list.size());
+    }
+  }
+
+  public final void readChunks(IDBStoreChunkReader chunkReader, List<Chunk> chunks, String where)
+  {
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Reading list chunk values for feature {0}.{1} of {2}", getContainingClass().getName(), //$NON-NLS-1$
+          getFeature().getName(), chunkReader.getRevision());
+    }
+
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = chunkReader.getAccessor().getStatementCache();
+    PreparedStatement stmt = null;
+    ResultSet resultSet = null;
+
+    IStoreChunkReader baseReader = null;
+
+    try
+    {
+      StringBuilder builder = new StringBuilder(sqlSelectChunksPrefix);
+      if (where != null)
+      {
+        builder.append(" AND "); //$NON-NLS-1$
+        builder.append(where);
+      }
+
+      builder.append(sqlOrderByIndex);
+
+      String sql = builder.toString();
+      stmt = statementCache.getPreparedStatement(sql, ReuseProbability.LOW);
+      idHandler.setCDOID(stmt, 1, chunkReader.getRevision().getID());
+      stmt.setInt(2, chunkReader.getRevision().getBranch().getID());
+      stmt.setInt(3, chunkReader.getRevision().getVersion());
+      stmt.setInt(4, chunkReader.getRevision().getVersion());
+
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Readung Chunks: {0}", stmt); //$NON-NLS-1$
+      }
+
+      resultSet = stmt.executeQuery();
+
+      int nextDBIndex = Integer.MAX_VALUE; // next available DB index
+      if (resultSet.next())
+      {
+        nextDBIndex = resultSet.getInt(1);
+      }
+
+      for (Chunk chunk : chunks)
+      {
+        int startIndex = chunk.getStartIndex();
+        int missingValueStartIndex = -1;
+
+        for (int i = 0; i < chunk.size(); i++)
+        {
+          int nextListIndex = startIndex + i; // next expected list index
+
+          if (nextDBIndex == nextListIndex)
+          {
+            // DB value is available. check first if missing indexes were present before.
+            if (missingValueStartIndex != -1)
+            {
+              // read missing indexes from missingValueStartIndex to currentIndex
+              if (baseReader == null)
+              {
+                baseReader = createBaseChunkReader(chunkReader.getAccessor(), chunkReader.getRevision().getID(),
+                    chunkReader.getRevision().getBranch().getID());
+              }
+              if (TRACER.isEnabled())
+              {
+                TRACER.format(
+                    "Scheduling range {0}-{1} to be read from base revision", missingValueStartIndex, nextListIndex); //$NON-NLS-1$
+              }
+
+              baseReader.addRangedChunk(missingValueStartIndex, nextListIndex);
+
+              // reset missingValueStartIndex
+              missingValueStartIndex = -1;
+            }
+
+            // now read value and set to chunk
+            Object value = typeMapping.readValue(resultSet);
+            if (TRACER.isEnabled())
+            {
+              TRACER.format("ChunkReader read value for index {0} from result set: {1}", nextDBIndex, value); //$NON-NLS-1$
+            }
+            chunk.add(i, value);
+
+            // advance DB cursor and read next available index
+            if (resultSet.next())
+            {
+              nextDBIndex = resultSet.getInt(1);
+            }
+            else
+            {
+              // no more DB indexes available, but we have to continue checking for gaps, therefore set to MAX_VALUE
+              nextDBIndex = Integer.MAX_VALUE;
+            }
+          }
+          else
+          {
+            // gap between next DB index and next list index detected.
+            // skip until end of chunk or until DB value becomes available
+            if (missingValueStartIndex == -1)
+            {
+              missingValueStartIndex = nextListIndex;
+            }
+          }
+        }
+
+        // chunk complete. check for missing values at the end of the chunk.
+        if (missingValueStartIndex != -1)
+        {
+          // read missing indexes from missingValueStartIndex to last chunk index
+          if (baseReader == null)
+          {
+            baseReader = createBaseChunkReader(chunkReader.getAccessor(), chunkReader.getRevision().getID(),
+                chunkReader.getRevision().getBranch().getID());
+          }
+
+          if (TRACER.isEnabled())
+          {
+            TRACER
+                .format(
+                    "Scheduling range {0}-{1} to be read from base revision", missingValueStartIndex, chunk.getStartIndex() + chunk.size()); //$NON-NLS-1$
+          }
+          baseReader.addRangedChunk(missingValueStartIndex, chunk.getStartIndex() + chunk.size());
+        }
+      }
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex);
+    }
+    finally
+    {
+      DBUtil.close(resultSet);
+      statementCache.releasePreparedStatement(stmt);
+    }
+
+    // now read missing values from base revision.
+    if (baseReader != null)
+    {
+      List<Chunk> baseChunks = baseReader.executeRead();
+
+      Iterator<Chunk> thisIterator = chunks.iterator();
+      Chunk thisChunk = thisIterator.next();
+
+      for (Chunk baseChunk : baseChunks)
+      {
+        int baseStartIndex = baseChunk.getStartIndex();
+
+        while (baseStartIndex > thisChunk.getStartIndex() + thisChunk.size())
+        {
+          // advance thisChunk, because it does not match baseChunk
+          thisChunk = thisIterator.next();
+        }
+
+        // baseChunk now corresponds to thisChunk, but startIndex of baseChunk may be higher.
+        // therefore calculate offset
+        int offset = baseStartIndex - thisChunk.getStartIndex();
+
+        // and copy values.
+        for (int i = 0; i < baseChunk.size(); i++)
+        {
+          if (TRACER.isEnabled())
+          {
+            TRACER.format("Copying base chunk reader value {0} at index {1} to current chunk reader at index {2}.",
+                baseChunk.get(i), baseChunk.getStartIndex() + i, thisChunk.getStartIndex() + i + offset);
+          }
+
+          thisChunk.add(i + offset, baseChunk.get(i));
+        } // finally, continue with the next baseChunk
+      }
+    }
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Reading list chunk values done for feature {0}.{1} of {2}", //$NON-NLS-1$
+          getContainingClass().getName(), getFeature().getName(), chunkReader.getRevision());
+    }
+  }
+
+  public void writeValues(IDBStoreAccessor accessor, InternalCDORevision revision)
+  {
+    CDOList values = revision.getList(getFeature());
+
+    int idx = 0;
+    for (Object element : values)
+    {
+      writeValue(accessor, revision, idx++, element);
+    }
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Writing done"); //$NON-NLS-1$
+    }
+  }
+
+  protected final void writeValue(IDBStoreAccessor accessor, CDORevision revision, int index, Object value)
+  {
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Writing value for feature {0}.{1} index {2} of {3} : {4}", //$NON-NLS-1$
+          getContainingClass().getName(), getFeature().getName(), index, revision, value);
+    }
+
+    addEntry(accessor, revision.getID(), revision.getBranch().getID(), revision.getVersion(), index, value);
+  }
+
+  /**
+   * Clear a list of a given revision.
+   * 
+   * @param accessor
+   *          the accessor to use
+   * @param id
+   *          the id of the revision from which to remove all items
+   * @param lastIndex
+   */
+  public void clearList(IDBStoreAccessor accessor, CDOID id, int branchId, int oldVersion, int newVersion, int lastIndex)
+  {
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+
+    try
+    {
+      // check for each index if the value exists in the current branch
+      for (int i = 0; i <= lastIndex; i++)
+      {
+        if (getValue(accessor, id, branchId, i, false) == null)
+        {
+          // if not, add a historic entry for missing ones.
+          addHistoricEntry(accessor, id, branchId, 0, newVersion, i, getValueFromBase(accessor, id, branchId, i));
+        }
+      }
+
+      // clear rest of the list
+      stmt = statementCache.getPreparedStatement(sqlClearList, ReuseProbability.HIGH);
+      stmt.setInt(1, newVersion);
+      getMappingStrategy().getStore().getIDHandler().setCDOID(stmt, 2, id);
+      stmt.setInt(3, branchId);
+
+      int result = DBUtil.update(stmt, false);
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("ClearList result: {0}", result); //$NON-NLS-1$
+      }
+    }
+    catch (SQLException e)
+    {
+      throw new DBException(e);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  public void objectDetached(IDBStoreAccessor accessor, CDOID id, long revised)
+  {
+    ITransaction transaction = accessor.getTransaction();
+    InternalCDORevision revision = (InternalCDORevision)transaction.getRevision(id);
+    int branchID = transaction.getBranch().getID();
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("objectDetached {1}", revision); //$NON-NLS-1$
+    }
+
+    clearList(accessor, id, branchID, revision.getVersion(), FINAL_VERSION, revision.getList(getFeature()).size() - 1);
+  }
+
+  public void processDelta(final IDBStoreAccessor accessor, final CDOID id, final int branchId, final int oldVersion,
+      final int newVersion, long created, CDOListFeatureDelta delta)
+  {
+    List<CDOFeatureDelta> listChanges = delta.getListChanges();
+    if (listChanges.size() == 0)
+    {
+      // nothing to do.
+      return;
+    }
+
+    InternalCDORevision originalRevision = (InternalCDORevision)accessor.getTransaction().getRevision(id);
+    int oldListSize = originalRevision.getList(getFeature()).size();
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("ListTableMapping.processDelta for revision {0} - previous list size: {1}", originalRevision, //$NON-NLS-1$
+          oldListSize);
+    }
+
+    // let the visitor collect the changes
+    ListDeltaVisitor visitor = new ListDeltaVisitor(accessor, originalRevision, branchId, oldVersion, newVersion);
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Processing deltas..."); //$NON-NLS-1$
+    }
+
+    // optimization: it's only necessary to process deltas
+    // starting with the last feature delta which clears the list
+    // (any operation before the clear is cascaded by it anyway)
+    int index = listChanges.size() - 1;
+    while (index > 0)
+    {
+      CDOFeatureDelta listDelta = listChanges.get(index);
+      if (listDelta instanceof CDOClearFeatureDelta || listDelta instanceof CDOUnsetFeatureDelta)
+      {
+        break;
+      }
+      index--;
+    }
+    while (index < listChanges.size())
+    {
+      listChanges.get(index++).accept(visitor);
+    }
+  }
+
+  /**
+   * @author Stefan Winkler
+   */
+  private class ListDeltaVisitor implements CDOFeatureDeltaVisitor
+  {
+    private IDBStoreAccessor accessor;
+
+    private CDOID id;
+
+    private int branchID;
+
+    private int oldVersion;
+
+    private int newVersion;
+
+    private int lastIndex;
+
+    public ListDeltaVisitor(IDBStoreAccessor accessor, InternalCDORevision originalRevision, int targetBranchID,
+        int oldVersion, int newVersion)
+    {
+      this.accessor = accessor;
+      id = originalRevision.getID();
+      branchID = targetBranchID;
+      this.oldVersion = oldVersion;
+      this.newVersion = newVersion;
+      lastIndex = originalRevision.getList(getFeature()).size() - 1;
+    }
+
+    public void visit(CDOMoveFeatureDelta delta)
+    {
+      int fromIdx = delta.getOldPosition();
+      int toIdx = delta.getNewPosition();
+
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Delta Moving: {0} to {1}", fromIdx, toIdx); //$NON-NLS-1$
+      }
+
+      Object value = getValue(accessor, id, branchID, fromIdx, true);
+
+      // remove the item
+      removeEntry(accessor, id, branchID, oldVersion, newVersion, fromIdx);
+
+      // adjust indexes and shift either up or down
+      if (fromIdx < toIdx)
+      {
+        moveOneUp(accessor, id, branchID, oldVersion, newVersion, fromIdx + 1, toIdx);
+      }
+      else
+      { // fromIdx > toIdx here
+        moveOneDown(accessor, id, branchID, oldVersion, newVersion, toIdx, fromIdx - 1);
+      }
+
+      // create the item
+      addEntry(accessor, id, branchID, newVersion, toIdx, value);
+    }
+
+    public void visit(CDOAddFeatureDelta delta)
+    {
+      int startIndex = delta.getIndex();
+      int endIndex = lastIndex;
+
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Delta Adding at: {0}", startIndex); //$NON-NLS-1$
+      }
+
+      if (startIndex <= endIndex)
+      {
+        // make room for the new item
+        moveOneDown(accessor, id, branchID, oldVersion, newVersion, startIndex, endIndex);
+      }
+
+      // create the item
+      addEntry(accessor, id, branchID, newVersion, startIndex, delta.getValue());
+
+      ++lastIndex;
+    }
+
+    public void visit(CDORemoveFeatureDelta delta)
+    {
+      int startIndex = delta.getIndex();
+      int endIndex = lastIndex;
+
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Delta Removing at: {0}", startIndex); //$NON-NLS-1$
+      }
+
+      // remove the item
+      removeEntry(accessor, id, branchID, oldVersion, newVersion, startIndex);
+
+      // make room for the new item
+      moveOneUp(accessor, id, branchID, oldVersion, newVersion, startIndex + 1, endIndex);
+
+      --lastIndex;
+    }
+
+    public void visit(CDOSetFeatureDelta delta)
+    {
+      int index = delta.getIndex();
+
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Delta Setting at: {0}", index); //$NON-NLS-1$
+      }
+
+      // remove the item
+      removeEntry(accessor, id, branchID, oldVersion, newVersion, index);
+
+      // create the item
+      addEntry(accessor, id, branchID, newVersion, index, delta.getValue());
+    }
+
+    public void visit(CDOUnsetFeatureDelta delta)
+    {
+      if (delta.getFeature().isUnsettable())
+      {
+        throw new ImplementationError("Should not be called"); //$NON-NLS-1$
+      }
+
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Delta Unsetting"); //$NON-NLS-1$
+      }
+
+      clearList(accessor, id, branchID, oldVersion, newVersion, lastIndex);
+      lastIndex = -1;
+    }
+
+    public void visit(CDOListFeatureDelta delta)
+    {
+      throw new ImplementationError("Should not be called"); //$NON-NLS-1$
+    }
+
+    public void visit(CDOClearFeatureDelta delta)
+    {
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Delta Clearing"); //$NON-NLS-1$
+      }
+
+      clearList(accessor, id, branchID, oldVersion, newVersion, lastIndex);
+      lastIndex = -1;
+    }
+
+    public void visit(CDOContainerFeatureDelta delta)
+    {
+      throw new ImplementationError("Should not be called"); //$NON-NLS-1$
+    }
+
+    private void moveOneUp(IDBStoreAccessor accessor, CDOID id, int branchId, int oldVersion, int newVersion,
+        int startIndex, int endIndex)
+    {
+      IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+      IPreparedStatementCache statementCache = accessor.getStatementCache();
+      PreparedStatement stmt = null;
+
+      try
+      {
+        stmt = statementCache.getPreparedStatement(sqlUpdateIndex, ReuseProbability.HIGH);
+
+        for (int index = startIndex; index <= endIndex; ++index)
+        {
+          if (TRACER.isEnabled())
+          {
+            TRACER.format("moveOneUp moving: {0} -> {1}", index, index - 1); //$NON-NLS-1$
+          }
+
+          int column = 1;
+          stmt.setInt(column++, index - 1);
+          idHandler.setCDOID(stmt, column++, id);
+          stmt.setInt(column++, branchId);
+          stmt.setInt(column++, newVersion);
+          stmt.setInt(column++, index);
+
+          int result = DBUtil.update(stmt, false);
+          switch (result)
+          {
+          case 1:
+            // entry for current revision was already present.
+            // index update succeeded.
+            if (TRACER.isEnabled())
+            {
+              TRACER.format("moveOneUp updated: {0} -> {1}", index, index - 1); //$NON-NLS-1$
+            }
+
+            break;
+          // no entry for current revision there.
+          case 0:
+            Object value = getValue(accessor, id, branchId, index, false);
+
+            if (value != null)
+            {
+              if (TRACER.isEnabled())
+              {
+                TRACER.format("moveOneUp remove: {0}", index); //$NON-NLS-1$
+              }
+
+              removeEntry(accessor, id, branchId, oldVersion, newVersion, index);
+            }
+            else
+            {
+              value = getValueFromBase(accessor, id, branchId, index);
+              {
+                TRACER.format("moveOneUp add historic entry at: {0}", index); //$NON-NLS-1$
+              }
+
+              addHistoricEntry(accessor, id, branchId, 0, newVersion, index, value);
+            }
+
+            if (TRACER.isEnabled())
+            {
+              TRACER.format("moveOneUp add: {0}", index - 1); //$NON-NLS-1$
+            }
+
+            addEntry(accessor, id, branchId, newVersion, index - 1, value);
+            break;
+          default:
+            if (TRACER.isEnabled())
+            {
+              TRACER.format("moveOneUp Too many results: {0} -> {1}: {2}", index, index + 1, result); //$NON-NLS-1$
+            }
+
+            throw new DBException("Too many results"); //$NON-NLS-1$
+          }
+        }
+      }
+      catch (SQLException e)
+      {
+        throw new DBException(e);
+      }
+      finally
+      {
+        statementCache.releasePreparedStatement(stmt);
+      }
+    }
+
+    private void moveOneDown(IDBStoreAccessor accessor, CDOID id, int branchId, int oldVersion, int newVersion,
+        int startIndex, int endIndex)
+    {
+      IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+      IPreparedStatementCache statementCache = accessor.getStatementCache();
+      PreparedStatement stmt = null;
+
+      try
+      {
+        stmt = statementCache.getPreparedStatement(sqlUpdateIndex, ReuseProbability.HIGH);
+
+        for (int index = endIndex; index >= startIndex; --index)
+        {
+          if (TRACER.isEnabled())
+          {
+            TRACER.format("moveOneDown moving: {0} -> {1}", index, index + 1); //$NON-NLS-1$
+          }
+
+          int column = 1;
+          stmt.setInt(column++, index + 1);
+          idHandler.setCDOID(stmt, column++, id);
+          stmt.setInt(column++, branchId);
+          stmt.setInt(column++, newVersion);
+          stmt.setInt(column++, index);
+
+          int result = DBUtil.update(stmt, false);
+          switch (result)
+          {
+          case 1:
+            // entry for current revision was already present.
+            // index update succeeded.
+
+            if (TRACER.isEnabled())
+            {
+              TRACER.format("moveOneDown updated: {0} -> {1}", index, index + 1); //$NON-NLS-1$
+            }
+
+            break;
+          case 0:
+            Object value = getValue(accessor, id, branchId, index, false);
+
+            if (value != null)
+            {
+              if (TRACER.isEnabled())
+              {
+                TRACER.format("moveOneDown remove: {0}", index); //$NON-NLS-1$
+              }
+
+              removeEntry(accessor, id, branchId, oldVersion, newVersion, index);
+            }
+            else
+            {
+              value = getValueFromBase(accessor, id, branchId, index);
+              {
+                TRACER.format("moveOneDown add historic entry at: {0}", index); //$NON-NLS-1$
+              }
+
+              addHistoricEntry(accessor, id, branchId, 0, newVersion, index, value);
+            }
+
+            if (TRACER.isEnabled())
+            {
+              TRACER.format("moveOneDown add: {0}", index + 1); //$NON-NLS-1$
+            }
+
+            addEntry(accessor, id, branchId, newVersion, index + 1, value);
+            break;
+          default:
+            if (TRACER.isEnabled())
+            {
+              TRACER.format("moveOneDown Too many results: {0} -> {1}: {2}", index, index + 1, result); //$NON-NLS-1$
+            }
+
+            throw new DBException("Too many results"); //$NON-NLS-1$
+          }
+        }
+      }
+      catch (SQLException e)
+      {
+        throw new DBException(e);
+      }
+      finally
+      {
+        statementCache.releasePreparedStatement(stmt);
+      }
+    }
+  }
+
+  private void addEntry(IDBStoreAccessor accessor, CDOID id, int branchId, int version, int index, Object value)
+  {
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Adding value for feature {0}.{1} index {2} of {3}:{4}v{5} : {6}", //$NON-NLS-1$
+          getContainingClass().getName(), getFeature().getName(), index, id, branchId, version, value);
+    }
+
+    try
+    {
+      stmt = statementCache.getPreparedStatement(sqlInsertEntry, ReuseProbability.HIGH);
+
+      int column = 1;
+      idHandler.setCDOID(stmt, column++, id);
+      stmt.setInt(column++, branchId);
+      stmt.setInt(column++, version); // versionAdded
+      stmt.setNull(column++, DBType.INTEGER.getCode()); // versionRemoved
+      stmt.setInt(column++, index);
+      typeMapping.setValue(stmt, column++, value);
+
+      DBUtil.update(stmt, true);
+    }
+    catch (SQLException e)
+    {
+      throw new DBException(e);
+    }
+    catch (IllegalStateException e)
+    {
+      throw new DBException(e);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  private void addHistoricEntry(IDBStoreAccessor accessor, CDOID id, int branchId, int versionAdded,
+      int versionRemoved, int index, Object value)
+  {
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format(
+          "Adding historic value for feature {0}.{1} index {2} of {3}:{4}v{5}-v{6} : {7}", //$NON-NLS-1$
+          getContainingClass().getName(), getFeature().getName(), index, id, branchId, versionAdded, versionRemoved,
+          value);
+    }
+
+    try
+    {
+      stmt = statementCache.getPreparedStatement(sqlInsertEntry, ReuseProbability.HIGH);
+
+      int column = 1;
+      idHandler.setCDOID(stmt, column++, id);
+      stmt.setInt(column++, branchId);
+      stmt.setInt(column++, versionAdded); // versionAdded
+      stmt.setInt(column++, versionRemoved); // versionRemoved
+      stmt.setInt(column++, index);
+      typeMapping.setValue(stmt, column++, value);
+
+      DBUtil.update(stmt, true);
+    }
+    catch (SQLException e)
+    {
+      throw new DBException(e);
+    }
+    catch (IllegalStateException e)
+    {
+      throw new DBException(e);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  private void removeEntry(IDBStoreAccessor accessor, CDOID id, int branchId, int oldVersion, int newVersion, int index)
+  {
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Removing value for feature {0}.{1} index {2} of {3}:{4}v{5}", //$NON-NLS-1$
+          getContainingClass().getName(), getFeature().getName(), index, id, branchId, newVersion);
+    }
+
+    try
+    {
+      // try to delete a temporary entry first
+      stmt = statementCache.getPreparedStatement(sqlDeleteEntry, ReuseProbability.HIGH);
+
+      int column = 1;
+      idHandler.setCDOID(stmt, column++, id);
+      stmt.setInt(column++, branchId);
+      stmt.setInt(column++, index);
+      stmt.setInt(column++, newVersion);
+
+      int result = DBUtil.update(stmt, false);
+      if (result == 1)
+      {
+        if (TRACER.isEnabled())
+        {
+          TRACER.format("removeEntry deleted: {0}", index); //$NON-NLS-1$
+        }
+      }
+      else if (result > 1)
+      {
+        if (TRACER.isEnabled())
+        {
+          TRACER.format("removeEntry Too many results: {0}: {1}", index, result); //$NON-NLS-1$
+        }
+
+        throw new DBException("Too many results"); //$NON-NLS-1$
+      }
+      else
+      {
+        // no temporary entry found, so mark the entry as removed
+        statementCache.releasePreparedStatement(stmt);
+        stmt = statementCache.getPreparedStatement(sqlRemoveEntry, ReuseProbability.HIGH);
+
+        column = 1;
+        stmt.setInt(column++, newVersion);
+        idHandler.setCDOID(stmt, column++, id);
+        stmt.setInt(column++, branchId);
+        stmt.setInt(column++, index);
+
+        result = DBUtil.update(stmt, false);
+
+        if (result == 0)
+        {
+          // no entry removed -> this means that we are in a branch and
+          // the entry has not been modified since the branch fork.
+          // therefore, we have to copy the base value and mark it as removed
+          Object value = getValueFromBase(accessor, id, branchId, index);
+          addHistoricEntry(accessor, id, branchId, 0, newVersion, index, value);
+        }
+      }
+    }
+    catch (SQLException e)
+    {
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Removing value for feature {0}.{1} index {2} of {3}:{4}v{5} FAILED {6}", //$NON-NLS-1$
+            getContainingClass().getName(), getFeature().getName(), index, id, branchId, newVersion, e.getMessage());
+      }
+
+      throw new DBException(e);
+    }
+    catch (IllegalStateException e)
+    {
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Removing value for feature {0}.{1} index {2} of {3}:{4}v{5} FAILED {6}", //$NON-NLS-1$
+            getContainingClass().getName(), getFeature().getName(), index, id, branchId, newVersion, e.getMessage());
+      }
+
+      throw new DBException(e);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  /**
+   * Read a single value from the current revision's list.
+   * 
+   * @param accessor
+   *          the store accessor
+   * @param id
+   *          the revision's ID
+   * @param branchId
+   *          the revision's branch ID
+   * @param index
+   *          the index from which to get the value
+   * @param getFromBase
+   *          if <code>true</code>, the value is recursively loaded from the base revision of a branch, if it is not
+   *          present in the current branch (because it has not been changed since the branch fork). If
+   *          <code>false</code>, <code>null</code> is returned in the former case.
+   */
+  private Object getValue(IDBStoreAccessor accessor, CDOID id, int branchId, int index, boolean getFromBase)
+  {
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+    Object result = null;
+
+    try
+    {
+      stmt = statementCache.getPreparedStatement(sqlGetValue, ReuseProbability.HIGH);
+      int column = 1;
+      idHandler.setCDOID(stmt, column++, id);
+      stmt.setInt(column++, branchId);
+      stmt.setInt(column++, index);
+
+      ResultSet resultSet = stmt.executeQuery();
+      if (resultSet.next())
+      {
+        result = typeMapping.readValue(resultSet);
+        if (TRACER.isEnabled())
+        {
+          TRACER.format("Read value (index {0}) from result set: {1}", index, result); //$NON-NLS-1$
+        }
+      }
+      else
+      {
+        // value is not in this branch.
+        // -> read from base revision
+        if (getFromBase)
+        {
+          result = getValueFromBase(accessor, id, branchId, index);
+        } // else: result remains null
+      }
+    }
+    catch (SQLException e)
+    {
+      throw new DBException(e);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+
+    return result;
+  }
+
+  /**
+   * Read a single value (at a given index) from the base revision
+   * 
+   * @param accessor
+   *          the DBStoreAccessor
+   * @param id
+   *          the ID of the revision
+   * @param branchID
+   *          the ID of the current (child) branch
+   * @param index
+   *          the index to read the value from
+   * @return the value which is at index <code>index</code> in revision with ID <code>id</code> in the parent branch at
+   *         the base of this branch (indicated by <code>branchID</code>).
+   */
+  private Object getValueFromBase(IDBStoreAccessor accessor, CDOID id, int branchID, int index)
+  {
+    IStoreChunkReader chunkReader = createBaseChunkReader(accessor, id, branchID);
+    chunkReader.addSimpleChunk(index);
+    List<Chunk> chunks = chunkReader.executeRead();
+    return chunks.get(0).get(0);
+  }
+
+  private IStoreChunkReader createBaseChunkReader(IDBStoreAccessor accessor, CDOID id, int branchID)
+  {
+    IRepository repository = accessor.getStore().getRepository();
+    CDOBranchPoint base = repository.getBranchManager().getBranch(branchID).getBase();
+    InternalCDORevision baseRevision = (InternalCDORevision)repository.getRevisionManager().getRevision(id, base, /*
+                                                                                                                   * referenceChunk
+                                                                                                                   * =
+                                                                                                                   */0, /*
+                                                                                                                         * prefetchDepth
+                                                                                                                         * =
+                                                                                                                         */
+        CDORevision.DEPTH_NONE, true);
+    IStoreChunkReader chunkReader = accessor.createChunkReader(baseRevision, getFeature());
+    return chunkReader;
+  }
+
+  public final boolean queryXRefs(IDBStoreAccessor accessor, String mainTableName, String mainTableWhere,
+      QueryXRefsContext context, String idString)
+  {
+
+    String tableName = getTable().getName();
+    String listJoin = getMappingStrategy().getListJoin("a_t", "l_t");
+
+    StringBuilder builder = new StringBuilder();
+    builder.append("SELECT l_t."); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_ID);
+    builder.append(", l_t."); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_VALUE);
+    builder.append(", l_t."); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_IDX);
+    builder.append(" FROM "); //$NON-NLS-1$
+    builder.append(tableName);
+    builder.append(" AS l_t, ");//$NON-NLS-1$
+    builder.append(mainTableName);
+    builder.append(" AS a_t WHERE ");//$NON-NLS-1$
+    builder.append("a_t." + mainTableWhere);//$NON-NLS-1$
+    builder.append(listJoin);
+    builder.append(" AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_VALUE);
+    builder.append(" IN "); //$NON-NLS-1$
+    builder.append(idString);
+    String sql = builder.toString();
+
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    ResultSet resultSet = null;
+    Statement stmt = null;
+
+    try
+    {
+      stmt = accessor.getConnection().createStatement();
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Query XRefs (list): {0}", sql);
+      }
+
+      resultSet = stmt.executeQuery(sql);
+      while (resultSet.next())
+      {
+        CDOID sourceID = idHandler.getCDOID(resultSet, 1);
+        CDOID targetID = idHandler.getCDOID(resultSet, 2);
+        int idx = resultSet.getInt(3);
+
+        boolean more = context.addXRef(targetID, sourceID, (EReference)getFeature(), idx);
+        if (TRACER.isEnabled())
+        {
+          TRACER.format("  add XRef to context: src={0}, tgt={1}, idx={2}", sourceID, targetID, idx);
+        }
+
+        if (!more)
+        {
+          if (TRACER.isEnabled())
+          {
+            TRACER.format("  result limit reached. Ignoring further results.");
+          }
+
+          return false;
+        }
+      }
+
+      return true;
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex);
+    }
+    finally
+    {
+      DBUtil.close(resultSet);
+      DBUtil.close(stmt);
+    }
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/DelegatingObjectTypeMapper.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/DelegatingObjectTypeMapper.java
new file mode 100644
index 0000000..3a1400d
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/DelegatingObjectTypeMapper.java
@@ -0,0 +1,127 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server.internal.db.mapping.horizontal;
+
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.model.CDOClassifierRef;
+import org.eclipse.emf.cdo.common.protocol.CDODataInput;
+import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
+import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
+import org.eclipse.emf.cdo.server.db.IIDHandler;
+import org.eclipse.emf.cdo.server.internal.db.IObjectTypeMapper;
+
+import org.eclipse.net4j.util.lifecycle.LifecycleUtil;
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+
+import org.eclipse.emf.ecore.EClass;
+
+import java.io.IOException;
+import java.sql.Connection;
+
+/**
+ * @author Eike Stepper
+ * @since 4.0
+ */
+public abstract class DelegatingObjectTypeMapper extends AbstractObjectTypeMapper
+{
+  private IObjectTypeMapper delegate;
+
+  public DelegatingObjectTypeMapper()
+  {
+  }
+
+  public IObjectTypeMapper getDelegate()
+  {
+    return delegate;
+  }
+
+  public void setDelegate(IObjectTypeMapper delegate)
+  {
+    this.delegate = delegate;
+  }
+
+  public CDOClassifierRef getObjectType(IDBStoreAccessor accessor, CDOID id)
+  {
+    CDOID type = doGetObjectType(accessor, id);
+    if (type != null)
+    {
+      EClass eClass = (EClass)getMetaDataManager().getMetaInstance(type);
+      return new CDOClassifierRef(eClass);
+    }
+
+    return delegate.getObjectType(accessor, id);
+  }
+
+  public void putObjectType(IDBStoreAccessor accessor, long timeStamp, CDOID id, EClass type)
+  {
+    CDOID classID = getMetaDataManager().getMetaID(type, timeStamp);
+    doPutObjectType(accessor, id, classID);
+
+    delegate.putObjectType(accessor, timeStamp, id, type);
+  }
+
+  public void removeObjectType(IDBStoreAccessor accessor, CDOID id)
+  {
+    doRemoveObjectType(accessor, id);
+    delegate.removeObjectType(accessor, id);
+  }
+
+  public CDOID getMaxID(Connection connection, IIDHandler idHandler)
+  {
+    CDOID maxID = doGetMaxID(connection, idHandler);
+    if (maxID != null)
+    {
+      return maxID;
+    }
+
+    return delegate.getMaxID(connection, idHandler);
+  }
+
+  public void rawExport(Connection connection, CDODataOutput out, long fromCommitTime, long toCommitTime)
+      throws IOException
+  {
+    delegate.rawExport(connection, out, fromCommitTime, toCommitTime);
+  }
+
+  public void rawImport(Connection connection, CDODataInput in, OMMonitor monitor) throws IOException
+  {
+    delegate.rawImport(connection, in, monitor);
+  }
+
+  @Override
+  protected void doBeforeActivate() throws Exception
+  {
+    super.doBeforeActivate();
+    checkState(delegate, "delegate");
+  }
+
+  @Override
+  protected void doActivate() throws Exception
+  {
+    super.doActivate();
+    LifecycleUtil.activate(delegate);
+  }
+
+  @Override
+  protected void doDeactivate() throws Exception
+  {
+    LifecycleUtil.deactivate(delegate);
+    super.doDeactivate();
+  }
+
+  protected abstract CDOID doGetObjectType(IDBStoreAccessor accessor, CDOID id);
+
+  protected abstract void doPutObjectType(IDBStoreAccessor accessor, CDOID id, CDOID type);
+
+  protected abstract void doRemoveObjectType(IDBStoreAccessor accessor, CDOID id);
+
+  protected abstract CDOID doGetMaxID(Connection connection, IIDHandler idHandler);
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalAuditClassMapping.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalAuditClassMapping.java
new file mode 100644
index 0000000..d1aee6e
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalAuditClassMapping.java
@@ -0,0 +1,742 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - major refactoring
+ *    Stefan Winkler - Bug 249610: [DB] Support external references (Implementation)
+ *    Lothar Werzinger - Bug 296440: [DB] Change RDB schema to improve scalability of to-many references in audit mode
+ *    Stefan Winkler - Bug 329025: [DB] Support branching for range-based mapping strategy
+ */
+package org.eclipse.emf.cdo.server.internal.db.mapping.horizontal;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.branch.CDOBranchVersion;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.revision.CDOList;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.delta.CDOAddFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOClearFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOContainerFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDeltaVisitor;
+import org.eclipse.emf.cdo.common.revision.delta.CDOListFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOMoveFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDORemoveFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOSetFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOUnsetFeatureDelta;
+import org.eclipse.emf.cdo.eresource.EresourcePackage;
+import org.eclipse.emf.cdo.server.IStoreAccessor.QueryXRefsContext;
+import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
+import org.eclipse.emf.cdo.server.db.IIDHandler;
+import org.eclipse.emf.cdo.server.db.IPreparedStatementCache;
+import org.eclipse.emf.cdo.server.db.IPreparedStatementCache.ReuseProbability;
+import org.eclipse.emf.cdo.server.db.mapping.IClassMappingAuditSupport;
+import org.eclipse.emf.cdo.server.db.mapping.IClassMappingDeltaSupport;
+import org.eclipse.emf.cdo.server.db.mapping.IListMappingDeltaSupport;
+import org.eclipse.emf.cdo.server.db.mapping.ITypeMapping;
+import org.eclipse.emf.cdo.server.internal.db.CDODBSchema;
+import org.eclipse.emf.cdo.server.internal.db.bundle.OM;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionDelta;
+
+import org.eclipse.net4j.db.DBException;
+import org.eclipse.net4j.db.DBUtil;
+import org.eclipse.net4j.util.ImplementationError;
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+import org.eclipse.net4j.util.om.monitor.OMMonitor.Async;
+import org.eclipse.net4j.util.om.trace.ContextTracer;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.Map;
+
+/**
+ * @author Eike Stepper
+ * @since 2.0
+ */
+public class HorizontalAuditClassMapping extends AbstractHorizontalClassMapping implements IClassMappingAuditSupport,
+    IClassMappingDeltaSupport
+{
+  private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG, HorizontalAuditClassMapping.class);
+
+  private String sqlInsertAttributes;
+
+  private String sqlSelectCurrentAttributes;
+
+  private String sqlSelectAllObjectIDs;
+
+  private String sqlSelectAttributesByTime;
+
+  private String sqlSelectAttributesByVersion;
+
+  private String sqlReviseAttributes;
+
+  private ThreadLocal<FeatureDeltaWriter> deltaWriter = new ThreadLocal<FeatureDeltaWriter>()
+  {
+    @Override
+    protected FeatureDeltaWriter initialValue()
+    {
+      return new FeatureDeltaWriter();
+    }
+  };
+
+  public HorizontalAuditClassMapping(AbstractHorizontalMappingStrategy mappingStrategy, EClass eClass)
+  {
+    super(mappingStrategy, eClass);
+
+    initSQLStrings();
+  }
+
+  private void initSQLStrings()
+  {
+    Map<EStructuralFeature, String> unsettableFields = getUnsettableFields();
+    Map<EStructuralFeature, String> listSizeFields = getListSizeFields();
+
+    // ----------- Select Revision ---------------------------
+    StringBuilder builder = new StringBuilder();
+
+    builder.append("SELECT "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_VERSION);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_CREATED);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_RESOURCE);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_CONTAINER);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_FEATURE);
+
+    for (ITypeMapping singleMapping : getValueMappings())
+    {
+      builder.append(", "); //$NON-NLS-1$
+      builder.append(singleMapping.getField());
+    }
+
+    if (unsettableFields != null)
+    {
+      for (String fieldName : unsettableFields.values())
+      {
+        builder.append(", "); //$NON-NLS-1$
+        builder.append(fieldName);
+      }
+    }
+
+    if (listSizeFields != null)
+    {
+      for (String fieldName : listSizeFields.values())
+      {
+        builder.append(", "); //$NON-NLS-1$
+        builder.append(fieldName);
+      }
+    }
+
+    builder.append(" FROM "); //$NON-NLS-1$
+    builder.append(getTable());
+    builder.append(" WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_ID);
+    builder.append("=? AND ("); //$NON-NLS-1$
+
+    String sqlSelectAttributesPrefix = builder.toString();
+
+    builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+    builder.append("=0)"); //$NON-NLS-1$
+
+    sqlSelectCurrentAttributes = builder.toString();
+
+    builder = new StringBuilder(sqlSelectAttributesPrefix);
+
+    builder.append(CDODBSchema.ATTRIBUTES_CREATED);
+    builder.append("<=? AND ("); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+    builder.append("=0 OR "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+    builder.append(">=?))"); //$NON-NLS-1$
+
+    sqlSelectAttributesByTime = builder.toString();
+
+    builder = new StringBuilder(sqlSelectAttributesPrefix);
+
+    builder.append("ABS(");
+    builder.append(CDODBSchema.ATTRIBUTES_VERSION);
+    builder.append(")=?)"); //$NON-NLS-1$
+
+    sqlSelectAttributesByVersion = builder.toString();
+
+    // ----------- Insert Attributes -------------------------
+    builder = new StringBuilder();
+    builder.append("INSERT INTO "); //$NON-NLS-1$
+    builder.append(getTable());
+
+    builder.append("("); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_ID);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_VERSION);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_CREATED);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_RESOURCE);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_CONTAINER);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_FEATURE);
+
+    for (ITypeMapping singleMapping : getValueMappings())
+    {
+      builder.append(", "); //$NON-NLS-1$
+      builder.append(singleMapping.getField());
+    }
+
+    if (unsettableFields != null)
+    {
+      for (String fieldName : unsettableFields.values())
+      {
+        builder.append(", "); //$NON-NLS-1$
+        builder.append(fieldName);
+      }
+    }
+
+    if (listSizeFields != null)
+    {
+      for (String fieldName : listSizeFields.values())
+      {
+        builder.append(", "); //$NON-NLS-1$
+        builder.append(fieldName);
+      }
+    }
+
+    builder.append(") VALUES (?, ?, ?, ?, ?, ?, ?"); //$NON-NLS-1$
+
+    for (int i = 0; i < getValueMappings().size(); i++)
+    {
+      builder.append(", ?"); //$NON-NLS-1$
+    }
+
+    if (unsettableFields != null)
+    {
+      for (int i = 0; i < unsettableFields.size(); i++)
+      {
+        builder.append(", ?"); //$NON-NLS-1$
+      }
+    }
+
+    if (listSizeFields != null)
+    {
+      for (int i = 0; i < listSizeFields.size(); i++)
+      {
+        builder.append(", ?"); //$NON-NLS-1$
+      }
+    }
+
+    builder.append(")"); //$NON-NLS-1$
+    sqlInsertAttributes = builder.toString();
+
+    // ----------- Update to set revised ----------------
+    builder = new StringBuilder("UPDATE "); //$NON-NLS-1$
+    builder.append(getTable());
+    builder.append(" SET "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+    builder.append("=? WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_ID);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+    builder.append("=0"); //$NON-NLS-1$
+    sqlReviseAttributes = builder.toString();
+
+    // ----------- Select all unrevised Object IDs ------
+    builder = new StringBuilder("SELECT "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_ID);
+    builder.append(" FROM "); //$NON-NLS-1$
+    builder.append(getTable());
+    builder.append(" WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+    builder.append("=0"); //$NON-NLS-1$
+    sqlSelectAllObjectIDs = builder.toString();
+  }
+
+  public boolean readRevision(IDBStoreAccessor accessor, InternalCDORevision revision, int listChunk)
+  {
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+
+    try
+    {
+      long timeStamp = revision.getTimeStamp();
+      if (timeStamp != CDOBranchPoint.UNSPECIFIED_DATE)
+      {
+        stmt = statementCache.getPreparedStatement(sqlSelectAttributesByTime, ReuseProbability.MEDIUM);
+        idHandler.setCDOID(stmt, 1, revision.getID());
+        stmt.setLong(2, timeStamp);
+        stmt.setLong(3, timeStamp);
+      }
+      else
+      {
+        stmt = statementCache.getPreparedStatement(sqlSelectCurrentAttributes, ReuseProbability.HIGH);
+        idHandler.setCDOID(stmt, 1, revision.getID());
+      }
+
+      // Read singleval-attribute table always (even without modeled attributes!)
+      boolean success = readValuesFromStatement(stmt, revision, accessor);
+
+      // Read multival tables only if revision exists
+      if (success && revision.getVersion() >= CDOBranchVersion.FIRST_VERSION)
+      {
+        readLists(accessor, revision, listChunk);
+      }
+
+      return success;
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  public boolean readRevisionByVersion(IDBStoreAccessor accessor, InternalCDORevision revision, int listChunk)
+  {
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+
+    try
+    {
+      stmt = statementCache.getPreparedStatement(sqlSelectAttributesByVersion, ReuseProbability.HIGH);
+      idHandler.setCDOID(stmt, 1, revision.getID());
+      stmt.setInt(2, revision.getVersion());
+
+      // Read singleval-attribute table always (even without modeled attributes!)
+      boolean success = readValuesFromStatement(stmt, revision, accessor);
+
+      // Read multival tables only if revision exists
+      if (success)
+      {
+        readLists(accessor, revision, listChunk);
+      }
+
+      return success;
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  public PreparedStatement createResourceQueryStatement(IDBStoreAccessor accessor, CDOID folderId, String name,
+      boolean exactMatch, CDOBranchPoint branchPoint)
+  {
+    EStructuralFeature nameFeature = EresourcePackage.eINSTANCE.getCDOResourceNode_Name();
+    long timeStamp = branchPoint.getTimeStamp();
+
+    ITypeMapping nameValueMapping = getValueMapping(nameFeature);
+    if (nameValueMapping == null)
+    {
+      throw new ImplementationError(nameFeature + " not found in ClassMapping " + this); //$NON-NLS-1$
+    }
+
+    StringBuilder builder = new StringBuilder();
+    builder.append("SELECT "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_ID);
+    builder.append(" FROM "); //$NON-NLS-1$
+    builder.append(getTable());
+    builder.append(" WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_VERSION);
+    builder.append(">0 AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_CONTAINER);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(nameValueMapping.getField());
+    if (name == null)
+    {
+      builder.append(" IS NULL"); //$NON-NLS-1$
+    }
+    else
+    {
+      builder.append(exactMatch ? "=? " : " LIKE ? "); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    builder.append(" AND ("); //$NON-NLS-1$
+
+    if (timeStamp == CDORevision.UNSPECIFIED_DATE)
+    {
+      builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+      builder.append("=0)"); //$NON-NLS-1$
+    }
+    else
+    {
+      builder.append(CDODBSchema.ATTRIBUTES_CREATED);
+      builder.append("<=? AND ("); //$NON-NLS-1$
+      builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+      builder.append("=0 OR "); //$NON-NLS-1$
+      builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+      builder.append(">=?))"); //$NON-NLS-1$
+    }
+
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+
+    try
+    {
+      int column = 1;
+
+      stmt = statementCache.getPreparedStatement(builder.toString(), ReuseProbability.MEDIUM);
+      idHandler.setCDOID(stmt, column++, folderId);
+
+      if (name != null)
+      {
+        String queryName = exactMatch ? name : name + "%"; //$NON-NLS-1$
+        nameValueMapping.setValue(stmt, column++, queryName);
+      }
+
+      if (timeStamp != CDORevision.UNSPECIFIED_DATE)
+      {
+        stmt.setLong(column++, timeStamp);
+        stmt.setLong(column++, timeStamp);
+      }
+
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Created Resource Query: {0}", stmt.toString()); //$NON-NLS-1$
+      }
+
+      return stmt;
+    }
+    catch (SQLException ex)
+    {
+      statementCache.releasePreparedStatement(stmt); // only release on error
+      throw new DBException(ex);
+    }
+  }
+
+  public PreparedStatement createObjectIDStatement(IDBStoreAccessor accessor)
+  {
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Created ObjectID Statement : {0}", sqlSelectAllObjectIDs); //$NON-NLS-1$
+    }
+
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    return statementCache.getPreparedStatement(sqlSelectAllObjectIDs, ReuseProbability.HIGH);
+  }
+
+  @Override
+  protected final void writeValues(IDBStoreAccessor accessor, InternalCDORevision revision)
+  {
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+
+    try
+    {
+      int column = 1;
+      stmt = statementCache.getPreparedStatement(sqlInsertAttributes, ReuseProbability.HIGH);
+      idHandler.setCDOID(stmt, column++, revision.getID());
+      stmt.setInt(column++, revision.getVersion());
+      stmt.setLong(column++, revision.getTimeStamp());
+      stmt.setLong(column++, revision.getRevised());
+      idHandler.setCDOID(stmt, column++, revision.getResourceID());
+      idHandler.setCDOID(stmt, column++, (CDOID)revision.getContainerID());
+      stmt.setInt(column++, revision.getContainingFeatureID());
+
+      int isSetCol = column + getValueMappings().size();
+
+      for (ITypeMapping mapping : getValueMappings())
+      {
+        EStructuralFeature feature = mapping.getFeature();
+        if (feature.isUnsettable())
+        {
+          if (revision.getValue(feature) == null)
+          {
+            stmt.setBoolean(isSetCol++, false);
+
+            // also set value column to default value
+            mapping.setDefaultValue(stmt, column++);
+
+            continue;
+          }
+
+          stmt.setBoolean(isSetCol++, true);
+        }
+
+        mapping.setValueFromRevision(stmt, column++, revision);
+      }
+
+      Map<EStructuralFeature, String> listSizeFields = getListSizeFields();
+      if (listSizeFields != null)
+      {
+        // isSetCol now points to the first listTableSize-column
+        column = isSetCol;
+
+        for (EStructuralFeature feature : listSizeFields.keySet())
+        {
+          CDOList list = revision.getList(feature);
+          stmt.setInt(column++, list.size());
+        }
+      }
+
+      DBUtil.update(stmt, true);
+    }
+    catch (SQLException e)
+    {
+      throw new DBException(e);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  @Override
+  protected void detachAttributes(IDBStoreAccessor accessor, CDOID id, int version, CDOBranch branch, long timeStamp,
+      OMMonitor mon)
+  {
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+
+    try
+    {
+      stmt = statementCache.getPreparedStatement(sqlInsertAttributes, ReuseProbability.HIGH);
+
+      int column = 1;
+
+      idHandler.setCDOID(stmt, column++, id);
+      stmt.setInt(column++, -version); // cdo_version
+      stmt.setLong(column++, timeStamp); // cdo_created
+      stmt.setLong(column++, CDOBranchPoint.UNSPECIFIED_DATE); // cdo_revised
+      idHandler.setCDOID(stmt, column++, CDOID.NULL); // resource
+      idHandler.setCDOID(stmt, column++, CDOID.NULL); // container
+      stmt.setInt(column++, 0); // containing feature ID
+
+      int isSetCol = column + getValueMappings().size();
+
+      for (ITypeMapping mapping : getValueMappings())
+      {
+        EStructuralFeature feature = mapping.getFeature();
+        if (feature.isUnsettable())
+        {
+          stmt.setBoolean(isSetCol++, false);
+        }
+
+        mapping.setDefaultValue(stmt, column++);
+      }
+
+      Map<EStructuralFeature, String> listSizeFields = getListSizeFields();
+      if (listSizeFields != null)
+      {
+        // list size columns begin after isSet-columns
+        column = isSetCol;
+
+        for (int i = 0; i < listSizeFields.size(); i++)
+        {
+          stmt.setInt(column++, 0);
+        }
+      }
+
+      DBUtil.update(stmt, true);
+    }
+    catch (SQLException e)
+    {
+      throw new DBException(e);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  @Override
+  protected void reviseOldRevision(IDBStoreAccessor accessor, CDOID id, CDOBranch branch, long revised)
+  {
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+
+    try
+    {
+      stmt = statementCache.getPreparedStatement(sqlReviseAttributes, ReuseProbability.HIGH);
+
+      stmt.setLong(1, revised);
+      idHandler.setCDOID(stmt, 2, id);
+
+      DBUtil.update(stmt, true);
+    }
+    catch (SQLException e)
+    {
+      throw new DBException(e);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  public void writeRevisionDelta(IDBStoreAccessor accessor, InternalCDORevisionDelta delta, long created,
+      OMMonitor monitor)
+  {
+    Async async = null;
+    monitor.begin();
+
+    try
+    {
+      try
+      {
+        async = monitor.forkAsync();
+        FeatureDeltaWriter writer = deltaWriter.get();
+        writer.process(accessor, delta, created);
+      }
+      finally
+      {
+        if (async != null)
+        {
+          async.stop();
+        }
+      }
+    }
+    finally
+    {
+      monitor.done();
+    }
+  }
+
+  @Override
+  protected String getListXRefsWhere(QueryXRefsContext context)
+  {
+    if (CDOBranch.MAIN_BRANCH_ID != context.getBranch().getID())
+    {
+      throw new IllegalArgumentException("Non-audit mode does not support branch specification");
+    }
+
+    StringBuilder builder = new StringBuilder();
+    long timeStamp = context.getTimeStamp();
+    if (timeStamp == CDORevision.UNSPECIFIED_DATE)
+    {
+      builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+      builder.append("=0"); //$NON-NLS-1$
+    }
+    else
+    {
+      builder.append(CDODBSchema.ATTRIBUTES_CREATED);
+      builder.append("<=");
+      builder.append(timeStamp);
+      builder.append(" AND ("); //$NON-NLS-1$
+      builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+      builder.append("=0 OR "); //$NON-NLS-1$
+      builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+      builder.append(">=");
+      builder.append(timeStamp);
+      builder.append(")"); //$NON-NLS-1$
+    }
+
+    return builder.toString();
+  }
+
+  /**
+   * @author Stefan Winkler
+   */
+  private class FeatureDeltaWriter implements CDOFeatureDeltaVisitor
+  {
+    private IDBStoreAccessor accessor;
+
+    private long created;
+
+    private CDOID id;
+
+    private int oldVersion;
+
+    private InternalCDORevision newRevision;
+
+    private int branchId;
+
+    public void process(IDBStoreAccessor accessor, InternalCDORevisionDelta delta, long created)
+    {
+      this.accessor = accessor;
+      this.created = created;
+      id = delta.getID();
+      branchId = delta.getBranch().getID();
+      oldVersion = delta.getVersion();
+
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("FeatureDeltaWriter: old version: {0}, new version: {1}", oldVersion, oldVersion + 1); //$NON-NLS-1$
+      }
+
+      InternalCDORevision originalRevision = (InternalCDORevision)accessor.getStore().getRepository()
+          .getRevisionManager().getRevisionByVersion(id, delta, 0, true);
+
+      newRevision = originalRevision.copy();
+
+      newRevision.setVersion(oldVersion + 1);
+      newRevision.setBranchPoint(delta.getBranch().getPoint(created));
+
+      // process revision delta tree
+      delta.accept(this);
+
+      long revised = newRevision.getTimeStamp() - 1;
+      reviseOldRevision(accessor, id, delta.getBranch(), revised);
+
+      writeValues(accessor, newRevision);
+    }
+
+    public void visit(CDOMoveFeatureDelta delta)
+    {
+      throw new ImplementationError("Should not be called"); //$NON-NLS-1$
+    }
+
+    public void visit(CDOAddFeatureDelta delta)
+    {
+      throw new ImplementationError("Should not be called"); //$NON-NLS-1$
+    }
+
+    public void visit(CDORemoveFeatureDelta delta)
+    {
+      throw new ImplementationError("Should not be called"); //$NON-NLS-1$
+    }
+
+    public void visit(CDOSetFeatureDelta delta)
+    {
+      delta.apply(newRevision);
+    }
+
+    public void visit(CDOUnsetFeatureDelta delta)
+    {
+      delta.apply(newRevision);
+    }
+
+    public void visit(CDOListFeatureDelta delta)
+    {
+      delta.apply(newRevision);
+      IListMappingDeltaSupport listMapping = (IListMappingDeltaSupport)getListMapping(delta.getFeature());
+      listMapping.processDelta(accessor, id, branchId, oldVersion, oldVersion + 1, created, delta);
+    }
+
+    public void visit(CDOClearFeatureDelta delta)
+    {
+      throw new ImplementationError("Should not be called"); //$NON-NLS-1$
+    }
+
+    public void visit(CDOContainerFeatureDelta delta)
+    {
+      delta.apply(newRevision);
+    }
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalAuditMappingStrategy.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalAuditMappingStrategy.java
new file mode 100644
index 0000000..c9eff1a
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalAuditMappingStrategy.java
@@ -0,0 +1,72 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - major refactoring
+ */
+package org.eclipse.emf.cdo.server.internal.db.mapping.horizontal;
+
+import org.eclipse.emf.cdo.server.db.mapping.IClassMapping;
+import org.eclipse.emf.cdo.server.db.mapping.IListMapping;
+import org.eclipse.emf.cdo.server.internal.db.CDODBSchema;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+/**
+ * @author Eike Stepper
+ * @since 2.0
+ */
+public class HorizontalAuditMappingStrategy extends AbstractHorizontalMappingStrategy
+{
+  public HorizontalAuditMappingStrategy()
+  {
+  }
+
+  public boolean hasAuditSupport()
+  {
+    return true;
+  }
+
+  public boolean hasBranchingSupport()
+  {
+    return false;
+  }
+
+  public boolean hasDeltaSupport()
+  {
+    return false;
+  }
+
+  @Override
+  public IClassMapping doCreateClassMapping(EClass eClass)
+  {
+    return new HorizontalAuditClassMapping(this, eClass);
+  }
+
+  @Override
+  public IListMapping doCreateListMapping(EClass containingClass, EStructuralFeature feature)
+  {
+    return new AuditListTableMapping(this, containingClass, feature);
+  }
+
+  @Override
+  public IListMapping doCreateFeatureMapMapping(EClass containingClass, EStructuralFeature feature)
+  {
+    return new AuditFeatureMapTableMapping(this, containingClass, feature);
+  }
+
+  @Override
+  public String getListJoin(String attrTable, String listTable)
+  {
+    String join = super.getListJoin(attrTable, listTable);
+    join += " AND " + attrTable + "." + CDODBSchema.ATTRIBUTES_VERSION;
+    join += "=" + listTable + "." + CDODBSchema.LIST_REVISION_VERSION;
+    return join;
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalAuditMappingStrategyWithRanges.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalAuditMappingStrategyWithRanges.java
new file mode 100644
index 0000000..93de7d8
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalAuditMappingStrategyWithRanges.java
@@ -0,0 +1,76 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - major refactoring
+ *    Stefan Winkler - Bug 329025: [DB] Support branching for range-based mapping strategy
+ */
+package org.eclipse.emf.cdo.server.internal.db.mapping.horizontal;
+
+import org.eclipse.emf.cdo.server.db.mapping.IClassMapping;
+import org.eclipse.emf.cdo.server.db.mapping.IListMapping;
+import org.eclipse.emf.cdo.server.internal.db.CDODBSchema;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+/**
+ * @author Eike Stepper
+ * @since 2.0
+ */
+public class HorizontalAuditMappingStrategyWithRanges extends AbstractHorizontalMappingStrategy
+{
+  public HorizontalAuditMappingStrategyWithRanges()
+  {
+  }
+
+  public boolean hasAuditSupport()
+  {
+    return true;
+  }
+
+  public boolean hasBranchingSupport()
+  {
+    return false;
+  }
+
+  public boolean hasDeltaSupport()
+  {
+    return true;
+  }
+
+  @Override
+  public IClassMapping doCreateClassMapping(EClass eClass)
+  {
+    return new HorizontalAuditClassMapping(this, eClass);
+  }
+
+  @Override
+  public IListMapping doCreateListMapping(EClass containingClass, EStructuralFeature feature)
+  {
+    return new AuditListTableMappingWithRanges(this, containingClass, feature);
+  }
+
+  @Override
+  public IListMapping doCreateFeatureMapMapping(EClass containingClass, EStructuralFeature feature)
+  {
+    return new AuditFeatureMapTableMappingWithRanges(this, containingClass, feature);
+  }
+
+  @Override
+  public String getListJoin(String attrTable, String listTable)
+  {
+    String join = super.getListJoin(attrTable, listTable);
+    join += " AND " + listTable + "." + CDODBSchema.LIST_REVISION_VERSION_ADDED;
+    join += "<=" + attrTable + "." + CDODBSchema.ATTRIBUTES_VERSION;
+    join += " AND (" + listTable + "." + CDODBSchema.LIST_REVISION_VERSION_REMOVED;
+    join += " IS NULL OR " + listTable + "." + CDODBSchema.LIST_REVISION_VERSION_REMOVED;
+    join += ">" + attrTable + "." + CDODBSchema.ATTRIBUTES_VERSION + ")";
+    return join;
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalBranchingClassMapping.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalBranchingClassMapping.java
new file mode 100644
index 0000000..6f337b2
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalBranchingClassMapping.java
@@ -0,0 +1,1124 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - major refactoring
+ *    Stefan Winkler - 249610: [DB] Support external references (Implementation)
+ *    Stefan Winkler - derived branch mapping from audit mapping
+ *    Stefan Winkler - Bug 329025: [DB] Support branching for range-based mapping strategy
+ */
+package org.eclipse.emf.cdo.server.internal.db.mapping.horizontal;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchManager;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.branch.CDOBranchVersion;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.model.CDOModelUtil;
+import org.eclipse.emf.cdo.common.revision.CDOList;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionHandler;
+import org.eclipse.emf.cdo.common.revision.CDORevisionManager;
+import org.eclipse.emf.cdo.common.revision.delta.CDOAddFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOClearFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOContainerFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDeltaVisitor;
+import org.eclipse.emf.cdo.common.revision.delta.CDOListFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOMoveFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDORemoveFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOSetFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOUnsetFeatureDelta;
+import org.eclipse.emf.cdo.eresource.EresourcePackage;
+import org.eclipse.emf.cdo.server.IRepository;
+import org.eclipse.emf.cdo.server.IStoreAccessor.QueryXRefsContext;
+import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
+import org.eclipse.emf.cdo.server.db.IIDHandler;
+import org.eclipse.emf.cdo.server.db.IPreparedStatementCache;
+import org.eclipse.emf.cdo.server.db.IPreparedStatementCache.ReuseProbability;
+import org.eclipse.emf.cdo.server.db.mapping.IClassMappingAuditSupport;
+import org.eclipse.emf.cdo.server.db.mapping.IClassMappingDeltaSupport;
+import org.eclipse.emf.cdo.server.db.mapping.IListMapping;
+import org.eclipse.emf.cdo.server.db.mapping.IListMappingDeltaSupport;
+import org.eclipse.emf.cdo.server.db.mapping.ITypeMapping;
+import org.eclipse.emf.cdo.server.internal.db.CDODBSchema;
+import org.eclipse.emf.cdo.server.internal.db.bundle.OM;
+import org.eclipse.emf.cdo.spi.common.commit.CDOChangeSetSegment;
+import org.eclipse.emf.cdo.spi.common.revision.DetachedCDORevision;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionDelta;
+import org.eclipse.emf.cdo.spi.server.InternalRepository;
+
+import org.eclipse.net4j.db.DBException;
+import org.eclipse.net4j.db.DBType;
+import org.eclipse.net4j.db.DBUtil;
+import org.eclipse.net4j.db.ddl.IDBField;
+import org.eclipse.net4j.db.ddl.IDBTable;
+import org.eclipse.net4j.util.ImplementationError;
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+import org.eclipse.net4j.util.om.monitor.OMMonitor.Async;
+import org.eclipse.net4j.util.om.trace.ContextTracer;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author Eike Stepper
+ * @author Stefan Winkler
+ * @since 3.0
+ */
+public class HorizontalBranchingClassMapping extends AbstractHorizontalClassMapping implements
+    IClassMappingAuditSupport, IClassMappingDeltaSupport
+{
+  /**
+   * @author Stefan Winkler
+   */
+  private class FeatureDeltaWriter implements CDOFeatureDeltaVisitor
+  {
+    private IDBStoreAccessor accessor;
+
+    private long created;
+
+    private CDOID id;
+
+    private CDOBranch targetBranch;
+
+    private int oldVersion;
+
+    private int newVersion;
+
+    private InternalCDORevision newRevision;
+
+    public void process(IDBStoreAccessor accessor, InternalCDORevisionDelta delta, long created)
+    {
+      this.accessor = accessor;
+      this.created = created;
+      id = delta.getID();
+      oldVersion = delta.getVersion();
+
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("FeatureDeltaWriter: old version: {0}, new version: {1}", oldVersion, oldVersion + 1); //$NON-NLS-1$
+      }
+
+      InternalCDORevision originalRevision = (InternalCDORevision)accessor.getTransaction().getRevision(id);
+      newRevision = originalRevision.copy();
+      targetBranch = accessor.getTransaction().getBranch();
+      newRevision.adjustForCommit(targetBranch, created);
+
+      newVersion = newRevision.getVersion();
+
+      // process revision delta tree
+      delta.accept(this);
+
+      if (newVersion != CDORevision.FIRST_VERSION)
+      {
+        reviseOldRevision(accessor, id, delta.getBranch(), newRevision.getTimeStamp() - 1);
+      }
+
+      writeValues(accessor, newRevision);
+    }
+
+    public void visit(CDOMoveFeatureDelta delta)
+    {
+      throw new ImplementationError("Should not be called"); //$NON-NLS-1$
+    }
+
+    public void visit(CDOAddFeatureDelta delta)
+    {
+      throw new ImplementationError("Should not be called"); //$NON-NLS-1$
+    }
+
+    public void visit(CDORemoveFeatureDelta delta)
+    {
+      throw new ImplementationError("Should not be called"); //$NON-NLS-1$
+    }
+
+    public void visit(CDOSetFeatureDelta delta)
+    {
+      delta.apply(newRevision);
+    }
+
+    public void visit(CDOUnsetFeatureDelta delta)
+    {
+      delta.apply(newRevision);
+    }
+
+    public void visit(CDOListFeatureDelta delta)
+    {
+      delta.apply(newRevision);
+      IListMappingDeltaSupport listMapping = (IListMappingDeltaSupport)getListMapping(delta.getFeature());
+      listMapping.processDelta(accessor, id, targetBranch.getID(), oldVersion, newVersion, created, delta);
+    }
+
+    public void visit(CDOClearFeatureDelta delta)
+    {
+      throw new ImplementationError("Should not be called"); //$NON-NLS-1$
+    }
+
+    public void visit(CDOContainerFeatureDelta delta)
+    {
+      delta.apply(newRevision);
+    }
+  }
+
+  private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG, HorizontalBranchingClassMapping.class);
+
+  private String sqlInsertAttributes;
+
+  private String sqlSelectCurrentAttributes;
+
+  private String sqlSelectAllObjectIDs;
+
+  private String sqlSelectAttributesByTime;
+
+  private String sqlSelectAttributesByVersion;
+
+  private String sqlReviseAttributes;
+
+  private String sqlSelectForHandle;
+
+  private String sqlSelectForChangeSet;
+
+  private ThreadLocal<FeatureDeltaWriter> deltaWriter = new ThreadLocal<FeatureDeltaWriter>()
+  {
+    @Override
+    protected FeatureDeltaWriter initialValue()
+    {
+      return new FeatureDeltaWriter();
+    }
+  };
+
+  public HorizontalBranchingClassMapping(AbstractHorizontalMappingStrategy mappingStrategy, EClass eClass)
+  {
+    super(mappingStrategy, eClass);
+
+    initSQLStrings();
+  }
+
+  @Override
+  protected IDBField addBranchingField(IDBTable table)
+  {
+    return table.addField(CDODBSchema.ATTRIBUTES_BRANCH, DBType.INTEGER, true);
+  }
+
+  private void initSQLStrings()
+  {
+    Map<EStructuralFeature, String> unsettableFields = getUnsettableFields();
+    Map<EStructuralFeature, String> listSizeFields = getListSizeFields();
+
+    // ----------- Select Revision ---------------------------
+    StringBuilder builder = new StringBuilder();
+
+    builder.append("SELECT "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_VERSION);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_CREATED);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_RESOURCE);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_CONTAINER);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_FEATURE);
+
+    for (ITypeMapping singleMapping : getValueMappings())
+    {
+      builder.append(", "); //$NON-NLS-1$
+      builder.append(singleMapping.getField());
+    }
+
+    if (unsettableFields != null)
+    {
+      for (String fieldName : unsettableFields.values())
+      {
+        builder.append(", "); //$NON-NLS-1$
+        builder.append(fieldName);
+      }
+    }
+
+    if (listSizeFields != null)
+    {
+      for (String fieldName : listSizeFields.values())
+      {
+        builder.append(", "); //$NON-NLS-1$
+        builder.append(fieldName);
+      }
+    }
+
+    builder.append(" FROM "); //$NON-NLS-1$
+    builder.append(getTable());
+    builder.append(" WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_ID);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_BRANCH);
+    builder.append("=? AND ("); //$NON-NLS-1$
+    String sqlSelectAttributesPrefix = builder.toString();
+
+    builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+    builder.append("=0)"); //$NON-NLS-1$
+
+    sqlSelectCurrentAttributes = builder.toString();
+
+    builder = new StringBuilder(sqlSelectAttributesPrefix);
+
+    builder.append(CDODBSchema.ATTRIBUTES_CREATED);
+    builder.append("<=? AND ("); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+    builder.append("=0 OR "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+    builder.append(">=?))"); //$NON-NLS-1$
+
+    sqlSelectAttributesByTime = builder.toString();
+
+    builder = new StringBuilder(sqlSelectAttributesPrefix);
+
+    builder.append("ABS("); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_VERSION);
+    builder.append(")=?)"); //$NON-NLS-1$
+
+    sqlSelectAttributesByVersion = builder.toString();
+
+    // ----------- Insert Attributes -------------------------
+    builder = new StringBuilder();
+    builder.append("INSERT INTO "); //$NON-NLS-1$
+    builder.append(getTable());
+
+    builder.append("("); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_ID);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_VERSION);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_BRANCH);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_CREATED);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_RESOURCE);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_CONTAINER);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_FEATURE);
+
+    for (ITypeMapping singleMapping : getValueMappings())
+    {
+      builder.append(", "); //$NON-NLS-1$
+      builder.append(singleMapping.getField());
+    }
+
+    if (unsettableFields != null)
+    {
+      for (String fieldName : unsettableFields.values())
+      {
+        builder.append(", "); //$NON-NLS-1$
+        builder.append(fieldName);
+      }
+    }
+
+    if (listSizeFields != null)
+    {
+      for (String fieldName : listSizeFields.values())
+      {
+        builder.append(", "); //$NON-NLS-1$
+        builder.append(fieldName);
+      }
+    }
+
+    builder.append(") VALUES (?, ?, ?, ?, ?, ?, ?, ?"); //$NON-NLS-1$
+
+    for (int i = 0; i < getValueMappings().size(); i++)
+    {
+      builder.append(", ?"); //$NON-NLS-1$
+    }
+
+    if (unsettableFields != null)
+    {
+      for (int i = 0; i < unsettableFields.size(); i++)
+      {
+        builder.append(", ?"); //$NON-NLS-1$
+      }
+    }
+
+    if (listSizeFields != null)
+    {
+      for (int i = 0; i < listSizeFields.size(); i++)
+      {
+        builder.append(", ?"); //$NON-NLS-1$
+      }
+    }
+
+    builder.append(")"); //$NON-NLS-1$
+    sqlInsertAttributes = builder.toString();
+
+    // ----------- Update to set revised ----------------
+    builder = new StringBuilder("UPDATE "); //$NON-NLS-1$
+    builder.append(getTable());
+    builder.append(" SET "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+    builder.append("=? WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_ID);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_BRANCH);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+    builder.append("=0"); //$NON-NLS-1$
+    sqlReviseAttributes = builder.toString();
+
+    // ----------- Select all unrevised Object IDs ------
+    builder = new StringBuilder("SELECT "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_ID);
+    builder.append(" FROM "); //$NON-NLS-1$
+    builder.append(getTable());
+    builder.append(" WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+    builder.append("=0"); //$NON-NLS-1$
+    sqlSelectAllObjectIDs = builder.toString();
+
+    // ----------- Select all revisions (for handleRevision) ---
+    builder = new StringBuilder("SELECT "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_ID);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_VERSION);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_BRANCH);
+    builder.append(" FROM "); //$NON-NLS-1$
+    builder.append(getTable());
+    sqlSelectForHandle = builder.toString();
+
+    // ----------- Select all revisions (for handleRevision) ---
+    builder = new StringBuilder("SELECT DISTINCT "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_ID);
+    builder.append(" FROM "); //$NON-NLS-1$
+    builder.append(getTable());
+    builder.append(" WHERE "); //$NON-NLS-1$
+    sqlSelectForChangeSet = builder.toString();
+  }
+
+  public boolean readRevision(IDBStoreAccessor accessor, InternalCDORevision revision, int listChunk)
+  {
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+
+    long timeStamp = revision.getTimeStamp();
+    int branchID = revision.getBranch().getID();
+
+    try
+    {
+      if (timeStamp != CDOBranchPoint.UNSPECIFIED_DATE)
+      {
+        stmt = statementCache.getPreparedStatement(sqlSelectAttributesByTime, ReuseProbability.MEDIUM);
+        idHandler.setCDOID(stmt, 1, revision.getID());
+        stmt.setInt(2, branchID);
+        stmt.setLong(3, timeStamp);
+        stmt.setLong(4, timeStamp);
+      }
+      else
+      {
+        stmt = statementCache.getPreparedStatement(sqlSelectCurrentAttributes, ReuseProbability.HIGH);
+        idHandler.setCDOID(stmt, 1, revision.getID());
+        stmt.setInt(2, branchID);
+      }
+
+      // Read singleval-attribute table always (even without modeled attributes!)
+      boolean success = readValuesFromStatement(stmt, revision, accessor);
+
+      // Read multival tables only if revision exists
+      if (success && revision.getVersion() >= CDOBranchVersion.FIRST_VERSION)
+      {
+        readLists(accessor, revision, listChunk);
+      }
+
+      return success;
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  public boolean readRevisionByVersion(IDBStoreAccessor accessor, InternalCDORevision revision, int listChunk)
+  {
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+
+    try
+    {
+      stmt = statementCache.getPreparedStatement(sqlSelectAttributesByVersion, ReuseProbability.HIGH);
+      idHandler.setCDOID(stmt, 1, revision.getID());
+      stmt.setInt(2, revision.getBranch().getID());
+      stmt.setInt(3, revision.getVersion());
+
+      // Read singleval-attribute table always (even without modeled attributes!)
+      boolean success = readValuesFromStatement(stmt, revision, accessor);
+
+      // Read multival tables only if revision exists
+      if (success)
+      {
+        readLists(accessor, revision, listChunk);
+      }
+
+      return success;
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  public PreparedStatement createResourceQueryStatement(IDBStoreAccessor accessor, CDOID folderId, String name,
+      boolean exactMatch, CDOBranchPoint branchPoint)
+  {
+    EStructuralFeature nameFeature = EresourcePackage.eINSTANCE.getCDOResourceNode_Name();
+
+    ITypeMapping nameValueMapping = getValueMapping(nameFeature);
+    if (nameValueMapping == null)
+    {
+      throw new ImplementationError(nameFeature + " not found in ClassMapping " + this); //$NON-NLS-1$
+    }
+
+    int branchID = branchPoint.getBranch().getID();
+    long timeStamp = branchPoint.getTimeStamp();
+
+    StringBuilder builder = new StringBuilder();
+    builder.append("SELECT "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_ID);
+    builder.append(" FROM "); //$NON-NLS-1$
+    builder.append(getTable());
+    builder.append(" WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_VERSION);
+    builder.append(">0 AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_BRANCH);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_CONTAINER);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(nameValueMapping.getField());
+    if (name == null)
+    {
+      builder.append(" IS NULL"); //$NON-NLS-1$
+    }
+    else
+    {
+      builder.append(exactMatch ? " =?" : " LIKE ?"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    builder.append(" AND ("); //$NON-NLS-1$
+
+    if (timeStamp == CDORevision.UNSPECIFIED_DATE)
+    {
+      builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+      builder.append("=0)"); //$NON-NLS-1$
+    }
+    else
+    {
+      builder.append(CDODBSchema.ATTRIBUTES_CREATED);
+      builder.append("<=? AND ("); //$NON-NLS-1$
+      builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+      builder.append("=0 OR "); //$NON-NLS-1$
+      builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+      builder.append(">=?))"); //$NON-NLS-1$
+    }
+
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+
+    try
+    {
+      int column = 1;
+
+      stmt = statementCache.getPreparedStatement(builder.toString(), ReuseProbability.MEDIUM);
+      stmt.setInt(column++, branchID);
+      idHandler.setCDOID(stmt, column++, folderId);
+
+      if (name != null)
+      {
+        String queryName = exactMatch ? name : name + "%"; //$NON-NLS-1$
+        nameValueMapping.setValue(stmt, column++, queryName);
+      }
+
+      if (timeStamp != CDORevision.UNSPECIFIED_DATE)
+      {
+        stmt.setLong(column++, timeStamp);
+        stmt.setLong(column++, timeStamp);
+      }
+
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Created Resource Query: {0}", stmt.toString()); //$NON-NLS-1$
+      }
+
+      return stmt;
+    }
+    catch (SQLException ex)
+    {
+      statementCache.releasePreparedStatement(stmt); // only release on error
+      throw new DBException(ex);
+    }
+  }
+
+  public PreparedStatement createObjectIDStatement(IDBStoreAccessor accessor)
+  {
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Created ObjectID Statement : {0}", sqlSelectAllObjectIDs); //$NON-NLS-1$
+    }
+
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    return statementCache.getPreparedStatement(sqlSelectAllObjectIDs, ReuseProbability.HIGH);
+  }
+
+  @Override
+  protected final void writeValues(IDBStoreAccessor accessor, InternalCDORevision revision)
+  {
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+
+    try
+    {
+      int column = 1;
+      stmt = statementCache.getPreparedStatement(sqlInsertAttributes, ReuseProbability.HIGH);
+      idHandler.setCDOID(stmt, column++, revision.getID());
+      stmt.setInt(column++, revision.getVersion());
+      stmt.setInt(column++, revision.getBranch().getID());
+      stmt.setLong(column++, revision.getTimeStamp());
+      stmt.setLong(column++, revision.getRevised());
+      idHandler.setCDOID(stmt, column++, revision.getResourceID());
+      idHandler.setCDOID(stmt, column++, (CDOID)revision.getContainerID());
+      stmt.setInt(column++, revision.getContainingFeatureID());
+
+      int isSetCol = column + getValueMappings().size();
+
+      for (ITypeMapping mapping : getValueMappings())
+      {
+        EStructuralFeature feature = mapping.getFeature();
+        if (feature.isUnsettable())
+        {
+          if (revision.getValue(feature) == null)
+          {
+            stmt.setBoolean(isSetCol++, false);
+
+            // also set value column to default value
+            mapping.setDefaultValue(stmt, column++);
+            continue;
+          }
+
+          stmt.setBoolean(isSetCol++, true);
+        }
+
+        mapping.setValueFromRevision(stmt, column++, revision);
+      }
+
+      Map<EStructuralFeature, String> listSizeFields = getListSizeFields();
+      if (listSizeFields != null)
+      {
+        // isSetCol now points to the first listTableSize-column
+        column = isSetCol;
+
+        for (EStructuralFeature feature : listSizeFields.keySet())
+        {
+          CDOList list = revision.getList(feature);
+          stmt.setInt(column++, list.size());
+        }
+      }
+
+      DBUtil.update(stmt, true);
+    }
+    catch (SQLException e)
+    {
+      throw new DBException(e);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  @Override
+  protected void detachAttributes(IDBStoreAccessor accessor, CDOID id, int version, CDOBranch branch, long timeStamp,
+      OMMonitor mon)
+  {
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+
+    try
+    {
+      stmt = statementCache.getPreparedStatement(sqlInsertAttributes, ReuseProbability.HIGH);
+
+      int column = 1;
+      idHandler.setCDOID(stmt, column++, id);
+      stmt.setInt(column++, -version); // cdo_version
+      stmt.setInt(column++, branch.getID());
+      stmt.setLong(column++, timeStamp); // cdo_created
+      stmt.setLong(column++, CDOBranchPoint.UNSPECIFIED_DATE); // cdo_revised
+      idHandler.setCDOID(stmt, column++, CDOID.NULL); // resource
+      idHandler.setCDOID(stmt, column++, CDOID.NULL); // container
+      stmt.setInt(column++, 0); // containing feature ID
+
+      int isSetCol = column + getValueMappings().size();
+
+      for (ITypeMapping mapping : getValueMappings())
+      {
+        EStructuralFeature feature = mapping.getFeature();
+        if (feature.isUnsettable())
+        {
+          stmt.setBoolean(isSetCol++, false);
+        }
+
+        mapping.setDefaultValue(stmt, column++);
+      }
+
+      Map<EStructuralFeature, String> listSizeFields = getListSizeFields();
+      if (listSizeFields != null)
+      {
+        // list size columns begin after isSet-columns
+        column = isSetCol;
+
+        for (int i = 0; i < listSizeFields.size(); i++)
+        {
+          stmt.setInt(column++, 0);
+        }
+      }
+
+      DBUtil.update(stmt, true);
+    }
+    catch (SQLException e)
+    {
+      throw new DBException(e);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  @Override
+  protected void reviseOldRevision(IDBStoreAccessor accessor, CDOID id, CDOBranch branch, long revised)
+  {
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+
+    try
+    {
+      stmt = statementCache.getPreparedStatement(sqlReviseAttributes, ReuseProbability.HIGH);
+
+      stmt.setLong(1, revised);
+      idHandler.setCDOID(stmt, 2, id);
+      stmt.setInt(3, branch.getID());
+
+      DBUtil.update(stmt, false); // No row affected if old revision from other branch!
+    }
+    catch (SQLException e)
+    {
+      throw new DBException(e);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  @Override
+  public void writeRevision(IDBStoreAccessor accessor, InternalCDORevision revision, boolean mapType, boolean revise,
+      OMMonitor monitor)
+  {
+    Async async = null;
+    monitor.begin(10);
+
+    try
+    {
+      try
+      {
+        async = monitor.forkAsync();
+        CDOID id = revision.getID();
+        if (mapType)
+        {
+          // put new objects into objectTypeMapper
+          long timeStamp = revision.getTimeStamp();
+          AbstractHorizontalMappingStrategy mappingStrategy = (AbstractHorizontalMappingStrategy)getMappingStrategy();
+          mappingStrategy.putObjectType(accessor, timeStamp, id, getEClass());
+        }
+        else if (revise && revision.getVersion() > CDOBranchVersion.FIRST_VERSION)
+        {
+          // if revision is not the first one, revise the old revision
+          long revised = revision.getTimeStamp() - 1;
+          reviseOldRevision(accessor, id, revision.getBranch(), revised);
+          for (IListMapping mapping : getListMappings())
+          {
+            mapping.objectDetached(accessor, id, revised);
+          }
+        }
+      }
+      finally
+      {
+        if (async != null)
+        {
+          async.stop();
+        }
+      }
+
+      try
+      {
+        async = monitor.forkAsync();
+        if (revision.isResourceFolder() || revision.isResource())
+        {
+          checkDuplicateResources(accessor, revision);
+        }
+      }
+      finally
+      {
+        if (async != null)
+        {
+          async.stop();
+        }
+      }
+
+      try
+      {
+        // Write attribute table always (even without modeled attributes!)
+        async = monitor.forkAsync();
+        writeValues(accessor, revision);
+      }
+      finally
+      {
+        if (async != null)
+        {
+          async.stop();
+        }
+      }
+
+      try
+      {
+        // Write list tables only if they exist
+        async = monitor.forkAsync(7);
+        if (getListMappings() != null)
+        {
+          writeLists(accessor, revision);
+        }
+      }
+      finally
+      {
+        if (async != null)
+        {
+          async.stop();
+        }
+      }
+    }
+    finally
+    {
+      monitor.done();
+    }
+  }
+
+  @Override
+  public void handleRevisions(IDBStoreAccessor accessor, CDOBranch branch, long timeStamp, boolean exactTime,
+      CDORevisionHandler handler)
+  {
+    StringBuilder builder = new StringBuilder(sqlSelectForHandle);
+    boolean whereAppend = false;
+
+    if (branch != null)
+    {
+      // TODO: Prepare this string literal
+      builder.append(" WHERE "); //$NON-NLS-1$
+      builder.append(CDODBSchema.ATTRIBUTES_BRANCH);
+      builder.append("=?"); //$NON-NLS-1$
+
+      whereAppend = true;
+    }
+
+    int timeParameters = 0;
+    if (timeStamp != CDOBranchPoint.INVALID_DATE)
+    {
+      if (exactTime)
+      {
+        if (timeStamp != CDOBranchPoint.UNSPECIFIED_DATE)
+        {
+          builder.append(whereAppend ? " AND " : " WHERE "); //$NON-NLS-1$ //$NON-NLS-2$
+          builder.append(CDODBSchema.ATTRIBUTES_CREATED);
+          builder.append("=?"); //$NON-NLS-1$
+          timeParameters = 1;
+        }
+      }
+      else
+      {
+        builder.append(whereAppend ? " AND " : " WHERE "); //$NON-NLS-1$ //$NON-NLS-2$
+        if (timeStamp != CDOBranchPoint.UNSPECIFIED_DATE)
+        {
+          builder.append(CDODBSchema.ATTRIBUTES_CREATED);
+          builder.append("<=? AND ("); //$NON-NLS-1$
+          builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+          builder.append("=0 OR "); //$NON-NLS-1$
+          builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+          builder.append(">=?)"); //$NON-NLS-1$
+          timeParameters = 2;
+        }
+        else
+        {
+          builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+          builder.append("="); //$NON-NLS-1$
+          builder.append(CDOBranchPoint.UNSPECIFIED_DATE);
+        }
+      }
+    }
+
+    IRepository repository = accessor.getStore().getRepository();
+    CDORevisionManager revisionManager = repository.getRevisionManager();
+    CDOBranchManager branchManager = repository.getBranchManager();
+
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+    ResultSet resultSet = null;
+
+    try
+    {
+      stmt = statementCache.getPreparedStatement(builder.toString(), ReuseProbability.LOW);
+
+      int column = 1;
+      if (branch != null)
+      {
+        stmt.setInt(column++, branch.getID());
+      }
+
+      for (int i = 0; i < timeParameters; i++)
+      {
+        stmt.setLong(column++, timeStamp);
+      }
+
+      resultSet = stmt.executeQuery();
+      while (resultSet.next())
+      {
+        CDOID id = idHandler.getCDOID(resultSet, 1);
+        int version = resultSet.getInt(2);
+
+        if (version >= CDOBranchVersion.FIRST_VERSION)
+        {
+          int branchID = resultSet.getInt(3);
+          CDOBranchVersion branchVersion = branchManager.getBranch(branchID).getVersion(Math.abs(version));
+          InternalCDORevision revision = (InternalCDORevision)revisionManager.getRevisionByVersion(id, branchVersion,
+              CDORevision.UNCHUNKED, true);
+
+          if (!handler.handleRevision(revision))
+          {
+            break;
+          }
+        }
+        else
+        {
+          // Tell handler about detached IDs
+          InternalCDORevision revision = new DetachedCDORevision(null, id, null, version, 0);
+          handler.handleRevision(revision);
+        }
+      }
+    }
+    catch (SQLException e)
+    {
+      throw new DBException(e);
+    }
+    finally
+    {
+      DBUtil.close(resultSet);
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  @Override
+  public Set<CDOID> readChangeSet(IDBStoreAccessor accessor, CDOChangeSetSegment[] segments)
+  {
+    StringBuilder builder = new StringBuilder(sqlSelectForChangeSet);
+    boolean isFirst = true;
+
+    for (int i = 0; i < segments.length; i++)
+    {
+      if (isFirst)
+      {
+        isFirst = false;
+      }
+      else
+      {
+        builder.append(" OR "); //$NON-NLS-1$
+      }
+
+      builder.append(CDODBSchema.ATTRIBUTES_BRANCH);
+      builder.append("=? AND "); //$NON-NLS-1$
+
+      builder.append(CDODBSchema.ATTRIBUTES_CREATED);
+      builder.append(">=?"); //$NON-NLS-1$
+      builder.append(" AND ("); //$NON-NLS-1$
+      builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+      builder.append("<=? OR "); //$NON-NLS-1$
+      builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+      builder.append("="); //$NON-NLS-1$
+      builder.append(CDOBranchPoint.UNSPECIFIED_DATE);
+      builder.append(")"); //$NON-NLS-1$
+    }
+
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+    ResultSet resultSet = null;
+
+    Set<CDOID> result = new HashSet<CDOID>();
+
+    try
+    {
+      stmt = statementCache.getPreparedStatement(builder.toString(), ReuseProbability.LOW);
+      int column = 1;
+      for (CDOChangeSetSegment segment : segments)
+      {
+        stmt.setInt(column++, segment.getBranch().getID());
+        stmt.setLong(column++, segment.getTimeStamp());
+        stmt.setLong(column++, segment.getEndTime());
+      }
+
+      resultSet = stmt.executeQuery();
+      while (resultSet.next())
+      {
+        CDOID id = idHandler.getCDOID(resultSet, 1);
+        result.add(id);
+      }
+
+      return result;
+    }
+    catch (SQLException e)
+    {
+      throw new DBException(e);
+    }
+    finally
+    {
+      DBUtil.close(resultSet);
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  @Override
+  protected String getListXRefsWhere(QueryXRefsContext context)
+  {
+    StringBuilder builder = new StringBuilder();
+    builder.append(CDODBSchema.ATTRIBUTES_BRANCH);
+    builder.append("=");
+    builder.append(context.getBranch().getID());
+    builder.append(" AND (");
+
+    long timeStamp = context.getTimeStamp();
+    if (timeStamp == CDORevision.UNSPECIFIED_DATE)
+    {
+      builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+      builder.append("=0)"); //$NON-NLS-1$
+    }
+    else
+    {
+      builder.append(CDODBSchema.ATTRIBUTES_CREATED);
+      builder.append("<=");
+      builder.append(timeStamp);
+      builder.append(" AND ("); //$NON-NLS-1$
+      builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+      builder.append("=0 OR "); //$NON-NLS-1$
+      builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+      builder.append(">=");
+      builder.append(timeStamp);
+      builder.append("))"); //$NON-NLS-1$
+    }
+
+    return builder.toString();
+  }
+
+  public void writeRevisionDelta(IDBStoreAccessor accessor, InternalCDORevisionDelta delta, long created,
+      OMMonitor monitor)
+  {
+    monitor.begin();
+
+    try
+    {
+      if (accessor.getTransaction().getBranch() != delta.getBranch())
+      {
+        // new branch -> decide, if branch should be copied
+        if (((HorizontalBranchingMappingStrategyWithRanges)getMappingStrategy()).shallCopyOnBranch())
+        {
+          doCopyOnBranch(accessor, delta, created, monitor.fork());
+          return;
+        }
+      }
+
+      Async async = null;
+
+      try
+      {
+        async = monitor.forkAsync();
+        FeatureDeltaWriter writer = deltaWriter.get();
+        writer.process(accessor, delta, created);
+      }
+      finally
+      {
+        if (async != null)
+        {
+          async.stop();
+        }
+      }
+    }
+    finally
+    {
+      monitor.done();
+    }
+  }
+
+  private void doCopyOnBranch(IDBStoreAccessor accessor, InternalCDORevisionDelta delta, long created, OMMonitor monitor)
+  {
+    monitor.begin(2);
+    try
+    {
+      InternalRepository repository = (InternalRepository)accessor.getStore().getRepository();
+
+      InternalCDORevision oldRevision = (InternalCDORevision)accessor.getTransaction().getRevision(delta.getID());
+      if (oldRevision == null)
+      {
+        throw new IllegalStateException("Origin revision not found for " + delta);
+      }
+
+      // Make sure all chunks are loaded
+      for (EStructuralFeature feature : CDOModelUtil.getAllPersistentFeatures(oldRevision.getEClass()))
+      {
+        if (feature.isMany())
+        {
+          repository.ensureChunk(oldRevision, feature, 0, oldRevision.getList(feature).size());
+        }
+      }
+
+      InternalCDORevision newRevision = oldRevision.copy();
+      newRevision.adjustForCommit(accessor.getTransaction().getBranch(), created);
+      delta.apply(newRevision);
+      monitor.worked();
+      writeRevision(accessor, newRevision, false, true, monitor.fork());
+    }
+    finally
+    {
+      monitor.done();
+    }
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalBranchingMappingStrategy.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalBranchingMappingStrategy.java
new file mode 100644
index 0000000..473883b
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalBranchingMappingStrategy.java
@@ -0,0 +1,196 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - major refactoring
+ */
+package org.eclipse.emf.cdo.server.internal.db.mapping.horizontal;
+
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.server.db.IIDHandler;
+import org.eclipse.emf.cdo.server.db.mapping.IClassMapping;
+import org.eclipse.emf.cdo.server.db.mapping.IListMapping;
+import org.eclipse.emf.cdo.server.internal.db.CDODBSchema;
+
+import org.eclipse.net4j.db.DBException;
+import org.eclipse.net4j.db.DBUtil;
+import org.eclipse.net4j.db.ddl.IDBTable;
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+import org.eclipse.net4j.util.om.monitor.OMMonitor.Async;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+/**
+ * @author Eike Stepper
+ * @since 2.0
+ */
+public class HorizontalBranchingMappingStrategy extends AbstractHorizontalMappingStrategy
+{
+  public HorizontalBranchingMappingStrategy()
+  {
+  }
+
+  public boolean hasAuditSupport()
+  {
+    return true;
+  }
+
+  public boolean hasBranchingSupport()
+  {
+    return true;
+  }
+
+  public boolean hasDeltaSupport()
+  {
+    return false;
+  }
+
+  @Override
+  public IClassMapping doCreateClassMapping(EClass eClass)
+  {
+    return new HorizontalBranchingClassMapping(this, eClass);
+  }
+
+  @Override
+  public IListMapping doCreateListMapping(EClass containingClass, EStructuralFeature feature)
+  {
+    return new BranchingListTableMapping(this, containingClass, feature);
+  }
+
+  @Override
+  public IListMapping doCreateFeatureMapMapping(EClass containingClass, EStructuralFeature feature)
+  {
+    return new BranchingFeatureMapTableMapping(this, containingClass, feature);
+  }
+
+  @Override
+  protected void rawImportReviseOldRevisions(Connection connection, IDBTable table, OMMonitor monitor)
+  {
+    String sqlUpdate = "UPDATE " + table + " SET " + CDODBSchema.ATTRIBUTES_REVISED + "=? WHERE "
+        + CDODBSchema.ATTRIBUTES_ID + "=? AND " + CDODBSchema.ATTRIBUTES_BRANCH + "=? AND "
+        + CDODBSchema.ATTRIBUTES_VERSION + "=?";
+
+    String sqlQuery = "SELECT cdo1." + CDODBSchema.ATTRIBUTES_ID + ", cdo1." + CDODBSchema.ATTRIBUTES_BRANCH
+        + ", cdo1." + CDODBSchema.ATTRIBUTES_VERSION + ", cdo2." + CDODBSchema.ATTRIBUTES_CREATED + " FROM " + table
+        + " cdo1, " + table + " cdo2 WHERE cdo1." + CDODBSchema.ATTRIBUTES_ID + "=cdo2." + CDODBSchema.ATTRIBUTES_ID
+        + " AND cdo1." + CDODBSchema.ATTRIBUTES_BRANCH + "=cdo2." + CDODBSchema.ATTRIBUTES_BRANCH + " AND (cdo1."
+        + CDODBSchema.ATTRIBUTES_VERSION + "=cdo2." + CDODBSchema.ATTRIBUTES_VERSION + "-1 OR (cdo1."
+        + CDODBSchema.ATTRIBUTES_VERSION + "+cdo2." + CDODBSchema.ATTRIBUTES_VERSION + "=-1 AND cdo1."
+        + CDODBSchema.ATTRIBUTES_VERSION + ">cdo2." + CDODBSchema.ATTRIBUTES_VERSION + ")) AND cdo1."
+        + CDODBSchema.ATTRIBUTES_REVISED + "=0";
+
+    IIDHandler idHandler = getStore().getIDHandler();
+    PreparedStatement stmtUpdate = null;
+    PreparedStatement stmtQuery = null;
+    ResultSet resultSet = null;
+
+    try
+    {
+      stmtUpdate = connection.prepareStatement(sqlUpdate);
+      stmtQuery = connection.prepareStatement(sqlQuery, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
+
+      resultSet = stmtQuery.executeQuery();
+      int size = DBUtil.getRowCount(resultSet);
+      if (size == 0)
+      {
+        return;
+      }
+
+      monitor.begin(2 * size);
+      while (resultSet.next())
+      {
+        CDOID id = idHandler.getCDOID(resultSet, 1);
+        int branch = resultSet.getInt(2);
+        int version = resultSet.getInt(3);
+        long revised = resultSet.getLong(4) - 1L;
+
+        stmtUpdate.setLong(1, revised);
+        idHandler.setCDOID(stmtUpdate, 2, id);
+        stmtUpdate.setInt(3, branch);
+        stmtUpdate.setInt(4, version);
+        stmtUpdate.addBatch();
+        monitor.worked();
+      }
+
+      Async async = monitor.forkAsync(size);
+      try
+      {
+        stmtUpdate.executeBatch();
+      }
+      finally
+      {
+        async.stop();
+      }
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex);
+    }
+    finally
+    {
+      DBUtil.close(resultSet);
+      DBUtil.close(stmtQuery);
+      DBUtil.close(stmtUpdate);
+      monitor.done();
+    }
+  }
+
+  @Override
+  protected void rawImportUnreviseNewRevisions(Connection connection, IDBTable table, long fromCommitTime,
+      long toCommitTime, OMMonitor monitor)
+  {
+    String sqlUpdate = "UPDATE " + table + " SET " + CDODBSchema.ATTRIBUTES_REVISED + "=0 WHERE "
+        + CDODBSchema.ATTRIBUTES_BRANCH + ">=0 AND " + CDODBSchema.ATTRIBUTES_CREATED + "<=" + toCommitTime + " AND "
+        + CDODBSchema.ATTRIBUTES_REVISED + ">" + toCommitTime + " AND " + CDODBSchema.ATTRIBUTES_VERSION + ">0";
+
+    PreparedStatement stmtUpdate = null;
+
+    try
+    {
+      stmtUpdate = connection.prepareStatement(sqlUpdate);
+
+      monitor.begin();
+      Async async = monitor.forkAsync();
+
+      try
+      {
+        stmtUpdate.executeUpdate();
+      }
+      finally
+      {
+        async.stop();
+      }
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex);
+    }
+    finally
+    {
+      DBUtil.close(stmtUpdate);
+      monitor.done();
+    }
+  }
+
+  @Override
+  public String getListJoin(String attrTable, String listTable)
+  {
+    String join = super.getListJoin(attrTable, listTable);
+    join += " AND " + attrTable + "." + CDODBSchema.ATTRIBUTES_VERSION;
+    join += "=" + listTable + "." + CDODBSchema.LIST_REVISION_VERSION;
+    join += " AND " + attrTable + "." + CDODBSchema.ATTRIBUTES_BRANCH;
+    join += "=" + listTable + "." + CDODBSchema.LIST_REVISION_BRANCH;
+    return join;
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalBranchingMappingStrategyWithRanges.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalBranchingMappingStrategyWithRanges.java
new file mode 100644
index 0000000..16508c6
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalBranchingMappingStrategyWithRanges.java
@@ -0,0 +1,95 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - major refactoring
+ *    Stefan Winkler - Bug 329025: [DB] Support branching for range-based mapping strategy
+ */
+package org.eclipse.emf.cdo.server.internal.db.mapping.horizontal;
+
+import org.eclipse.emf.cdo.server.db.CDODBUtil;
+import org.eclipse.emf.cdo.server.db.mapping.IClassMapping;
+import org.eclipse.emf.cdo.server.db.mapping.IListMapping;
+import org.eclipse.emf.cdo.server.internal.db.CDODBSchema;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+/**
+ * @author Eike Stepper
+ * @since 2.0
+ */
+public class HorizontalBranchingMappingStrategyWithRanges extends AbstractHorizontalMappingStrategy
+{
+  private boolean copyOnBranch;
+
+  public HorizontalBranchingMappingStrategyWithRanges()
+  {
+  }
+
+  public boolean hasAuditSupport()
+  {
+    return true;
+  }
+
+  public boolean hasBranchingSupport()
+  {
+    return true;
+  }
+
+  public boolean hasDeltaSupport()
+  {
+    return true;
+  }
+
+  public boolean shallCopyOnBranch()
+  {
+    return copyOnBranch;
+  }
+
+  @Override
+  public IClassMapping doCreateClassMapping(EClass eClass)
+  {
+    return new HorizontalBranchingClassMapping(this, eClass);
+  }
+
+  @Override
+  public IListMapping doCreateListMapping(EClass containingClass, EStructuralFeature feature)
+  {
+    return new BranchingListTableMappingWithRanges(this, containingClass, feature);
+  }
+
+  @Override
+  public IListMapping doCreateFeatureMapMapping(EClass containingClass, EStructuralFeature feature)
+  {
+    return new BranchingFeatureMapTableMappingWithRanges(this, containingClass, feature);
+  }
+
+  @Override
+  public String getListJoin(String attrTable, String listTable)
+  {
+    String join = super.getListJoin(attrTable, listTable);
+    join += " AND " + listTable + "." + CDODBSchema.LIST_REVISION_VERSION_ADDED;
+    join += "<=" + attrTable + "." + CDODBSchema.ATTRIBUTES_VERSION;
+    join += " AND (" + listTable + "." + CDODBSchema.LIST_REVISION_VERSION_REMOVED;
+    join += " IS NULL OR " + listTable + "." + CDODBSchema.LIST_REVISION_VERSION_REMOVED;
+    join += ">" + attrTable + "." + CDODBSchema.ATTRIBUTES_VERSION;
+    join += ") AND " + attrTable + "." + CDODBSchema.ATTRIBUTES_BRANCH;
+    join += "=" + listTable + "." + CDODBSchema.LIST_REVISION_BRANCH;
+    return join;
+  }
+
+  @Override
+  protected void doAfterActivate() throws Exception
+  {
+    super.doAfterActivate();
+
+    String value = getProperties().get(CDODBUtil.PROP_COPY_ON_BRANCH);
+    copyOnBranch = value == null ? false : Boolean.valueOf(value);
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalMappingStrategy.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalMappingStrategy.java
new file mode 100644
index 0000000..836014b
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalMappingStrategy.java
@@ -0,0 +1,272 @@
+/**

+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    Eike Stepper - initial API and implementation

+ */

+package org.eclipse.emf.cdo.server.internal.db.mapping.horizontal;

+

+import org.eclipse.emf.cdo.common.branch.CDOBranch;

+import org.eclipse.emf.cdo.common.id.CDOID;

+import org.eclipse.emf.cdo.common.model.CDOClassifierRef;

+import org.eclipse.emf.cdo.common.protocol.CDODataInput;

+import org.eclipse.emf.cdo.common.protocol.CDODataOutput;

+import org.eclipse.emf.cdo.common.revision.CDORevisionHandler;

+import org.eclipse.emf.cdo.server.IRepository.Props;

+import org.eclipse.emf.cdo.server.IStoreAccessor.QueryResourcesContext;

+import org.eclipse.emf.cdo.server.IStoreAccessor.QueryXRefsContext;

+import org.eclipse.emf.cdo.server.db.CDODBUtil;

+import org.eclipse.emf.cdo.server.db.IDBStore;

+import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;

+import org.eclipse.emf.cdo.server.db.mapping.IClassMapping;

+import org.eclipse.emf.cdo.server.db.mapping.IListMapping;

+import org.eclipse.emf.cdo.server.db.mapping.IMappingStrategy;

+import org.eclipse.emf.cdo.server.db.mapping.ITypeMapping;

+import org.eclipse.emf.cdo.spi.common.commit.CDOChangeSetSegment;

+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit;

+

+import org.eclipse.net4j.db.IDBAdapter;

+import org.eclipse.net4j.util.collection.CloseableIterator;

+import org.eclipse.net4j.util.lifecycle.Lifecycle;

+import org.eclipse.net4j.util.lifecycle.LifecycleUtil;

+import org.eclipse.net4j.util.om.monitor.OMMonitor;

+

+import org.eclipse.emf.ecore.EClass;

+import org.eclipse.emf.ecore.ENamedElement;

+import org.eclipse.emf.ecore.EStructuralFeature;

+

+import java.io.IOException;

+import java.sql.Connection;

+import java.util.HashMap;

+import java.util.Map;

+import java.util.Set;

+

+/**

+ * @author Eike Stepper

+ */

+public class HorizontalMappingStrategy extends Lifecycle implements IMappingStrategy

+{

+  private Map<String, String> properties;

+

+  private IDBStore store;

+

+  private IMappingStrategy delegate;

+

+  public HorizontalMappingStrategy()

+  {

+  }

+

+  public IMappingStrategy getDelegate()

+  {

+    return delegate;

+  }

+

+  public Map<String, String> getProperties()

+  {

+    if (delegate != null)

+    {

+      return delegate.getProperties();

+    }

+

+    if (properties != null)

+    {

+      return properties;

+    }

+

+    return new HashMap<String, String>();

+  }

+

+  public void setProperties(Map<String, String> properties)

+  {

+    if (delegate != null)

+    {

+      delegate.setProperties(properties);

+    }

+    else

+    {

+      this.properties = properties;

+    }

+  }

+

+  public IDBStore getStore()

+  {

+    if (delegate != null)

+    {

+      return delegate.getStore();

+    }

+

+    return store;

+  }

+

+  public void setStore(IDBStore store)

+  {

+    if (delegate != null)

+    {

+      delegate.setStore(store);

+    }

+    else

+    {

+      this.store = store;

+    }

+  }

+

+  public ITypeMapping createValueMapping(EStructuralFeature feature)

+  {

+    return delegate.createValueMapping(feature);

+  }

+

+  public IListMapping createListMapping(EClass containingClass, EStructuralFeature feature)

+  {

+    return delegate.createListMapping(containingClass, feature);

+  }

+

+  public String getTableName(ENamedElement element)

+  {

+    return delegate.getTableName(element);

+  }

+

+  public String getTableName(EClass containingClass, EStructuralFeature feature)

+  {

+    return delegate.getTableName(containingClass, feature);

+  }

+

+  public String getFieldName(EStructuralFeature feature)

+  {

+    return delegate.getFieldName(feature);

+  }

+

+  public void createMapping(Connection connection, InternalCDOPackageUnit[] packageUnits, OMMonitor monitor)

+  {

+    delegate.createMapping(connection, packageUnits, monitor);

+  }

+

+  public void removeMapping(Connection connection, InternalCDOPackageUnit[] packageUnits)

+  {

+    delegate.removeMapping(connection, packageUnits);

+  }

+

+  public IClassMapping getClassMapping(EClass eClass)

+  {

+    return delegate.getClassMapping(eClass);

+  }

+

+  public Map<EClass, IClassMapping> getClassMappings()

+  {

+    return delegate.getClassMappings();

+  }

+

+  public Map<EClass, IClassMapping> getClassMappings(boolean createOnDemand)

+  {

+    return delegate.getClassMappings(createOnDemand);

+  }

+

+  public boolean hasDeltaSupport()

+  {

+    return delegate.hasDeltaSupport();

+  }

+

+  public boolean hasAuditSupport()

+  {

+    return delegate.hasAuditSupport();

+  }

+

+  public boolean hasBranchingSupport()

+  {

+    return delegate.hasBranchingSupport();

+  }

+

+  public void queryResources(IDBStoreAccessor accessor, QueryResourcesContext context)

+  {

+    delegate.queryResources(accessor, context);

+  }

+

+  public void queryXRefs(IDBStoreAccessor accessor, QueryXRefsContext context)

+  {

+    delegate.queryXRefs(accessor, context);

+  }

+

+  public CDOClassifierRef readObjectType(IDBStoreAccessor accessor, CDOID id)

+  {

+    return delegate.readObjectType(accessor, id);

+  }

+

+  public CloseableIterator<CDOID> readObjectIDs(IDBStoreAccessor accessor)

+  {

+    return delegate.readObjectIDs(accessor);

+  }

+

+  public void repairAfterCrash(IDBAdapter dbAdapter, Connection connection)

+  {

+    delegate.repairAfterCrash(dbAdapter, connection);

+  }

+

+  public void handleRevisions(IDBStoreAccessor accessor, EClass eClass, CDOBranch branch, long timeStamp,

+      boolean exactTime, CDORevisionHandler handler)

+  {

+    delegate.handleRevisions(accessor, eClass, branch, timeStamp, exactTime, handler);

+  }

+

+  public Set<CDOID> readChangeSet(IDBStoreAccessor accessor, OMMonitor monitor, CDOChangeSetSegment[] segments)

+  {

+    return delegate.readChangeSet(accessor, monitor, segments);

+  }

+

+  public void rawExport(IDBStoreAccessor accessor, CDODataOutput out, int lastReplicatedBranchID, int lastBranchID,

+      long lastReplicatedCommitTime, long lastCommitTime) throws IOException

+  {

+    delegate.rawExport(accessor, out, lastReplicatedBranchID, lastBranchID, lastReplicatedCommitTime, lastCommitTime);

+  }

+

+  public void rawImport(IDBStoreAccessor accessor, CDODataInput in, long fromCommitTime, long toCommitTime,

+      OMMonitor monitor) throws IOException

+  {

+    delegate.rawImport(accessor, in, fromCommitTime, toCommitTime, monitor);

+  }

+

+  public String getListJoin(String attrTable, String listTable)

+  {

+    return delegate.getListJoin(attrTable, listTable);

+  }

+

+  @Override

+  protected void doActivate() throws Exception

+  {

+    super.doActivate();

+

+    boolean auditing = getBooleanProperty(Props.SUPPORTING_AUDITS);

+    boolean branching = getBooleanProperty(Props.SUPPORTING_BRANCHES);

+

+    boolean withRanges = false;

+    if (auditing || branching)

+    {

+      withRanges = getBooleanProperty(CDODBUtil.PROP_WITH_RANGES);

+    }

+

+    delegate = CDODBUtil.createHorizontalMappingStrategy(auditing, branching, withRanges);

+    delegate.setStore(store);

+    delegate.setProperties(properties);

+    LifecycleUtil.activate(delegate);

+  }

+

+  @Override

+  protected void doDeactivate() throws Exception

+  {

+    LifecycleUtil.deactivate(delegate);

+    super.doDeactivate();

+  }

+

+  private boolean getBooleanProperty(String prop)

+  {

+    String valueAudits = properties.get(prop);

+    if (valueAudits != null)

+    {

+      return Boolean.valueOf(valueAudits);

+    }

+

+    return false;

+  }

+}

diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalNonAuditClassMapping.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalNonAuditClassMapping.java
new file mode 100644
index 0000000..d37b714
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalNonAuditClassMapping.java
@@ -0,0 +1,764 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - major refactoring
+ *    Stefan Winkler - 249610: [DB] Support external references (Implementation)
+ *    Stefan Winkler - Bug 329025: [DB] Support branching for range-based mapping strategy
+ */
+package org.eclipse.emf.cdo.server.internal.db.mapping.horizontal;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.revision.CDOList;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.delta.CDOAddFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOClearFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOContainerFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDeltaVisitor;
+import org.eclipse.emf.cdo.common.revision.delta.CDOListFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOMoveFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDORemoveFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOSetFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOUnsetFeatureDelta;
+import org.eclipse.emf.cdo.eresource.EresourcePackage;
+import org.eclipse.emf.cdo.server.IStoreAccessor.QueryXRefsContext;
+import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
+import org.eclipse.emf.cdo.server.db.IIDHandler;
+import org.eclipse.emf.cdo.server.db.IPreparedStatementCache;
+import org.eclipse.emf.cdo.server.db.IPreparedStatementCache.ReuseProbability;
+import org.eclipse.emf.cdo.server.db.mapping.IClassMappingDeltaSupport;
+import org.eclipse.emf.cdo.server.db.mapping.IListMappingDeltaSupport;
+import org.eclipse.emf.cdo.server.db.mapping.ITypeMapping;
+import org.eclipse.emf.cdo.server.internal.db.CDODBSchema;
+import org.eclipse.emf.cdo.server.internal.db.bundle.OM;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionDelta;
+
+import org.eclipse.net4j.db.DBException;
+import org.eclipse.net4j.db.DBUtil;
+import org.eclipse.net4j.util.ImplementationError;
+import org.eclipse.net4j.util.collection.Pair;
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+import org.eclipse.net4j.util.om.monitor.OMMonitor.Async;
+import org.eclipse.net4j.util.om.trace.ContextTracer;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Eike Stepper
+ * @since 2.0
+ */
+public class HorizontalNonAuditClassMapping extends AbstractHorizontalClassMapping implements IClassMappingDeltaSupport
+{
+  private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG, HorizontalNonAuditClassMapping.class);
+
+  private String sqlSelectAllObjectIDs;
+
+  private String sqlSelectCurrentAttributes;
+
+  private String sqlInsertAttributes;
+
+  private String sqlUpdateAffix;
+
+  private String sqlUpdatePrefix;
+
+  private String sqlUpdateContainerPart;
+
+  private ThreadLocal<FeatureDeltaWriter> deltaWriter = new ThreadLocal<FeatureDeltaWriter>()
+  {
+    @Override
+    protected FeatureDeltaWriter initialValue()
+    {
+      return new FeatureDeltaWriter();
+    }
+  };
+
+  public HorizontalNonAuditClassMapping(AbstractHorizontalMappingStrategy mappingStrategy, EClass eClass)
+  {
+    super(mappingStrategy, eClass);
+
+    initSQLStrings();
+  }
+
+  private void initSQLStrings()
+  {
+    Map<EStructuralFeature, String> unsettableFields = getUnsettableFields();
+    Map<EStructuralFeature, String> listSizeFields = getListSizeFields();
+
+    // ----------- Select Revision ---------------------------
+    StringBuilder builder = new StringBuilder();
+
+    builder.append("SELECT "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_VERSION);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_CREATED);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_RESOURCE);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_CONTAINER);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_FEATURE);
+
+    for (ITypeMapping singleMapping : getValueMappings())
+    {
+      builder.append(", "); //$NON-NLS-1$
+      builder.append(singleMapping.getField());
+    }
+
+    if (unsettableFields != null)
+    {
+      for (String fieldName : unsettableFields.values())
+      {
+        builder.append(", "); //$NON-NLS-1$
+        builder.append(fieldName);
+      }
+    }
+
+    if (listSizeFields != null)
+    {
+      for (String fieldName : listSizeFields.values())
+      {
+        builder.append(", "); //$NON-NLS-1$
+        builder.append(fieldName);
+      }
+    }
+
+    builder.append(" FROM "); //$NON-NLS-1$
+    builder.append(getTable());
+    builder.append(" WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_ID);
+    builder.append("=?"); //$NON-NLS-1$
+
+    sqlSelectCurrentAttributes = builder.toString();
+
+    // ----------- Insert Attributes -------------------------
+    builder = new StringBuilder();
+    builder.append("INSERT INTO "); //$NON-NLS-1$
+    builder.append(getTable());
+
+    builder.append("("); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_ID);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_VERSION);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_CREATED);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_REVISED);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_RESOURCE);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_CONTAINER);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_FEATURE);
+
+    for (ITypeMapping singleMapping : getValueMappings())
+    {
+      builder.append(", "); //$NON-NLS-1$
+      builder.append(singleMapping.getField());
+    }
+
+    if (unsettableFields != null)
+    {
+      for (String fieldName : unsettableFields.values())
+      {
+        builder.append(", "); //$NON-NLS-1$
+        builder.append(fieldName);
+      }
+    }
+
+    if (listSizeFields != null)
+    {
+      for (String fieldName : listSizeFields.values())
+      {
+        builder.append(", "); //$NON-NLS-1$
+        builder.append(fieldName);
+      }
+    }
+
+    builder.append(") VALUES (?, ?, ?, ?, ?, ?, ?"); //$NON-NLS-1$
+    for (int i = 0; i < getValueMappings().size(); i++)
+    {
+      builder.append(", ?"); //$NON-NLS-1$
+    }
+
+    if (unsettableFields != null)
+    {
+      for (int i = 0; i < unsettableFields.size(); i++)
+      {
+        builder.append(", ?"); //$NON-NLS-1$
+      }
+    }
+
+    if (listSizeFields != null)
+    {
+      for (int i = 0; i < listSizeFields.size(); i++)
+      {
+        builder.append(", ?"); //$NON-NLS-1$
+      }
+    }
+
+    builder.append(")"); //$NON-NLS-1$
+    sqlInsertAttributes = builder.toString();
+
+    // ----------- Select all unrevised Object IDs ------
+    builder = new StringBuilder("SELECT "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_ID);
+    builder.append(" FROM "); //$NON-NLS-1$
+    builder.append(getTable());
+    sqlSelectAllObjectIDs = builder.toString();
+
+    // ----------- Update attributes --------------------
+    builder = new StringBuilder("UPDATE "); //$NON-NLS-1$
+    builder.append(getTable());
+    builder.append(" SET "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_VERSION);
+    builder.append("=? ,"); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_CREATED);
+    builder.append("=? "); //$NON-NLS-1$
+    sqlUpdatePrefix = builder.toString();
+
+    builder = new StringBuilder(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_RESOURCE);
+    builder.append("=? ,"); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_CONTAINER);
+    builder.append("=? ,"); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_FEATURE);
+    builder.append("=? "); //$NON-NLS-1$
+    sqlUpdateContainerPart = builder.toString();
+
+    builder = new StringBuilder(" WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_ID);
+    builder.append("=? "); //$NON-NLS-1$
+    sqlUpdateAffix = builder.toString();
+  }
+
+  @Override
+  protected void writeValues(IDBStoreAccessor accessor, InternalCDORevision revision)
+  {
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+
+    try
+    {
+      int column = 1;
+      stmt = statementCache.getPreparedStatement(sqlInsertAttributes, ReuseProbability.HIGH);
+      idHandler.setCDOID(stmt, column++, revision.getID());
+      stmt.setInt(column++, revision.getVersion());
+      stmt.setLong(column++, revision.getTimeStamp());
+      stmt.setLong(column++, revision.getRevised());
+      idHandler.setCDOID(stmt, column++, revision.getResourceID());
+      idHandler.setCDOID(stmt, column++, (CDOID)revision.getContainerID());
+      stmt.setInt(column++, revision.getContainingFeatureID());
+
+      int isSetCol = column + getValueMappings().size();
+
+      for (ITypeMapping mapping : getValueMappings())
+      {
+        EStructuralFeature feature = mapping.getFeature();
+        if (feature.isUnsettable())
+        {
+          if (revision.getValue(feature) == null)
+          {
+            stmt.setBoolean(isSetCol++, false);
+
+            // also set value column to default value
+            mapping.setDefaultValue(stmt, column++);
+            continue;
+          }
+
+          stmt.setBoolean(isSetCol++, true);
+        }
+
+        mapping.setValueFromRevision(stmt, column++, revision);
+      }
+
+      Map<EStructuralFeature, String> listSizeFields = getListSizeFields();
+      if (listSizeFields != null)
+      {
+        // isSetCol now points to the first listTableSize-column
+        column = isSetCol;
+
+        for (EStructuralFeature feature : listSizeFields.keySet())
+        {
+          CDOList list = revision.getList(feature);
+          stmt.setInt(column++, list.size());
+        }
+      }
+
+      DBUtil.update(stmt, true);
+    }
+    catch (SQLException e)
+    {
+      throw new DBException(e);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  public PreparedStatement createObjectIDStatement(IDBStoreAccessor accessor)
+  {
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Created ObjectID Statement : {0}", sqlSelectAllObjectIDs); //$NON-NLS-1$
+    }
+
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    return statementCache.getPreparedStatement(sqlSelectAllObjectIDs, ReuseProbability.HIGH);
+  }
+
+  public PreparedStatement createResourceQueryStatement(IDBStoreAccessor accessor, CDOID folderId, String name,
+      boolean exactMatch, CDOBranchPoint branchPoint)
+  {
+    long timeStamp = branchPoint.getTimeStamp();
+    if (timeStamp != CDORevision.UNSPECIFIED_DATE)
+    {
+      throw new IllegalArgumentException("Non-audit store does not support explicit timeStamp in resource query"); //$NON-NLS-1$
+    }
+
+    EStructuralFeature nameFeature = EresourcePackage.eINSTANCE.getCDOResourceNode_Name();
+
+    ITypeMapping nameValueMapping = getValueMapping(nameFeature);
+    if (nameValueMapping == null)
+    {
+      throw new ImplementationError(nameFeature + " not found in ClassMapping " + this); //$NON-NLS-1$
+    }
+
+    StringBuilder builder = new StringBuilder();
+    builder.append("SELECT "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_ID);
+    builder.append(" FROM "); //$NON-NLS-1$
+    builder.append(getTable());
+    builder.append(" WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_VERSION);
+    builder.append(">0 AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.ATTRIBUTES_CONTAINER);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(nameValueMapping.getField());
+    if (name == null)
+    {
+      builder.append(" IS NULL"); //$NON-NLS-1$
+    }
+    else
+    {
+      builder.append(exactMatch ? "=? " : " LIKE ? "); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+
+    try
+    {
+      int column = 1;
+
+      stmt = statementCache.getPreparedStatement(builder.toString(), ReuseProbability.MEDIUM);
+      idHandler.setCDOID(stmt, column++, folderId);
+
+      if (name != null)
+      {
+        String queryName = exactMatch ? name : name + "%"; //$NON-NLS-1$
+        nameValueMapping.setValue(stmt, column++, queryName);
+      }
+
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("Created Resource Query: {0}", stmt.toString()); //$NON-NLS-1$
+      }
+
+      return stmt;
+    }
+    catch (SQLException ex)
+    {
+      statementCache.releasePreparedStatement(stmt); // only release on error
+      throw new DBException(ex);
+    }
+  }
+
+  public boolean readRevision(IDBStoreAccessor accessor, InternalCDORevision revision, int listChunk)
+  {
+    long timeStamp = revision.getTimeStamp();
+    if (timeStamp != CDOBranchPoint.UNSPECIFIED_DATE)
+    {
+      throw new UnsupportedOperationException("Mapping strategy does not support audits"); //$NON-NLS-1$
+    }
+
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+
+    try
+    {
+      stmt = statementCache.getPreparedStatement(sqlSelectCurrentAttributes, ReuseProbability.HIGH);
+      idHandler.setCDOID(stmt, 1, revision.getID());
+
+      // Read singleval-attribute table always (even without modeled attributes!)
+      boolean success = readValuesFromStatement(stmt, revision, accessor);
+
+      // Read multival tables only if revision exists
+      if (success)
+      {
+        readLists(accessor, revision, listChunk);
+      }
+
+      return success;
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  @Override
+  protected void detachAttributes(IDBStoreAccessor accessor, CDOID id, int version, CDOBranch branch, long timeStamp,
+      OMMonitor mon)
+  {
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+
+    try
+    {
+      stmt = statementCache.getPreparedStatement(sqlUpdatePrefix + sqlUpdateAffix, ReuseProbability.HIGH);
+      stmt.setInt(1, -version);
+      stmt.setLong(2, timeStamp);
+      idHandler.setCDOID(stmt, 3, id);
+
+      DBUtil.update(stmt, true);
+    }
+    catch (SQLException e)
+    {
+      throw new DBException(e);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  public void writeRevisionDelta(IDBStoreAccessor accessor, InternalCDORevisionDelta delta, long created,
+      OMMonitor monitor)
+  {
+    Async async = null;
+    monitor.begin();
+
+    try
+    {
+      try
+      {
+        async = monitor.forkAsync();
+        FeatureDeltaWriter writer = deltaWriter.get();
+        writer.process(accessor, delta, created);
+      }
+      finally
+      {
+        if (async != null)
+        {
+          async.stop();
+        }
+      }
+    }
+    finally
+    {
+      monitor.done();
+    }
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  private class FeatureDeltaWriter implements CDOFeatureDeltaVisitor
+  {
+    private CDOID id;
+
+    private int oldVersion;
+
+    private long created;
+
+    private IDBStoreAccessor accessor;
+
+    private boolean updateContainer;
+
+    private List<Pair<ITypeMapping, Object>> attributeChanges;
+
+    private List<Pair<EStructuralFeature, Integer>> listSizeChanges;
+
+    private int newContainingFeatureID;
+
+    private CDOID newContainerID;
+
+    private CDOID newResourceID;
+
+    private int branchId;
+
+    private int newVersion;
+
+    /*
+     * this is a temporary copy of the revision to track list size changes...
+     */
+    private InternalCDORevision tempRevision;
+
+    public FeatureDeltaWriter()
+    {
+      attributeChanges = new ArrayList<Pair<ITypeMapping, Object>>();
+      listSizeChanges = new ArrayList<Pair<EStructuralFeature, Integer>>();
+    }
+
+    protected void reset()
+    {
+      attributeChanges.clear();
+      listSizeChanges.clear();
+      updateContainer = false;
+    }
+
+    public void process(IDBStoreAccessor a, CDORevisionDelta d, long c)
+    {
+      // set context
+      id = d.getID();
+
+      branchId = d.getBranch().getID();
+      oldVersion = d.getVersion();
+      newVersion = oldVersion + 1;
+      created = c;
+      accessor = a;
+
+      tempRevision = (InternalCDORevision)accessor.getTransaction().getRevision(id).copy();
+
+      // process revision delta tree
+      d.accept(this);
+
+      updateAttributes();
+      // clean up
+      reset();
+    }
+
+    public void visit(CDOMoveFeatureDelta delta)
+    {
+      throw new ImplementationError("Should not be called"); //$NON-NLS-1$
+    }
+
+    public void visit(CDOSetFeatureDelta delta)
+    {
+      if (delta.getFeature().isMany())
+      {
+        throw new ImplementationError("Should not be called"); //$NON-NLS-1$
+      }
+
+      ITypeMapping am = getValueMapping(delta.getFeature());
+      if (am == null)
+      {
+        throw new IllegalArgumentException("AttributeMapping for " + delta.getFeature() + " is null!"); //$NON-NLS-1$ //$NON-NLS-2$
+      }
+
+      attributeChanges.add(new Pair<ITypeMapping, Object>(am, delta.getValue()));
+    }
+
+    public void visit(CDOUnsetFeatureDelta delta)
+    {
+      // TODO: correct this when DBStore implements unsettable features
+      // see Bugs 259868 and 263010
+      ITypeMapping tm = getValueMapping(delta.getFeature());
+      attributeChanges.add(new Pair<ITypeMapping, Object>(tm, null));
+    }
+
+    public void visit(CDOListFeatureDelta delta)
+    {
+      EStructuralFeature feature = delta.getFeature();
+
+      IListMappingDeltaSupport listMapping = (IListMappingDeltaSupport)getListMapping(feature);
+      listMapping.processDelta(accessor, id, branchId, oldVersion, oldVersion + 1, created, delta);
+
+      int oldSize = tempRevision.getList(feature).size();
+      delta.apply(tempRevision);
+      int newSize = tempRevision.getList(feature).size();
+
+      if (oldSize != newSize)
+      {
+        listSizeChanges.add(new Pair<EStructuralFeature, Integer>(feature, newSize));
+      }
+    }
+
+    public void visit(CDOClearFeatureDelta delta)
+    {
+      throw new ImplementationError("Should not be called"); //$NON-NLS-1$
+    }
+
+    public void visit(CDOAddFeatureDelta delta)
+    {
+      throw new ImplementationError("Should not be called"); //$NON-NLS-1$
+    }
+
+    public void visit(CDORemoveFeatureDelta delta)
+    {
+      throw new ImplementationError("Should not be called"); //$NON-NLS-1$
+    }
+
+    public void visit(CDOContainerFeatureDelta delta)
+    {
+      newContainingFeatureID = delta.getContainerFeatureID();
+      newContainerID = (CDOID)delta.getContainerID();
+      newResourceID = delta.getResourceID();
+      updateContainer = true;
+    }
+
+    private void updateAttributes()
+    {
+      IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+      IPreparedStatementCache statementCache = accessor.getStatementCache();
+      PreparedStatement stmt = null;
+
+      try
+      {
+        int column = 1;
+
+        stmt = statementCache.getPreparedStatement(buildUpdateStatement(), ReuseProbability.MEDIUM);
+        stmt.setInt(column++, newVersion);
+        stmt.setLong(column++, created);
+        if (updateContainer)
+        {
+          idHandler.setCDOID(stmt, column++, newResourceID, created);
+          idHandler.setCDOID(stmt, column++, newContainerID, created);
+          stmt.setInt(column++, newContainingFeatureID);
+        }
+
+        column = setUpdateAttributeValues(attributeChanges, stmt, column);
+        column = setUpdateListSizeChanges(listSizeChanges, stmt, column);
+
+        idHandler.setCDOID(stmt, column++, id);
+
+        DBUtil.update(stmt, true);
+      }
+      catch (SQLException e)
+      {
+        throw new DBException(e);
+      }
+      finally
+      {
+        statementCache.releasePreparedStatement(stmt);
+      }
+    }
+
+    private String buildUpdateStatement()
+    {
+      StringBuilder builder = new StringBuilder(sqlUpdatePrefix);
+      if (updateContainer)
+      {
+        builder.append(sqlUpdateContainerPart);
+      }
+
+      for (Pair<ITypeMapping, Object> change : attributeChanges)
+      {
+        builder.append(", "); //$NON-NLS-1$
+        ITypeMapping typeMapping = change.getElement1();
+        builder.append(typeMapping.getField());
+        builder.append("=?"); //$NON-NLS-1$
+
+        if (typeMapping.getFeature().isUnsettable())
+        {
+          builder.append(", "); //$NON-NLS-1$
+          builder.append(getUnsettableFields().get(typeMapping.getFeature()));
+          builder.append("=?"); //$NON-NLS-1$
+        }
+      }
+
+      for (Pair<EStructuralFeature, Integer> change : listSizeChanges)
+      {
+        builder.append(", "); //$NON-NLS-1$
+        EStructuralFeature feature = change.getElement1();
+        builder.append(getListSizeFields().get(feature));
+        builder.append("=?"); //$NON-NLS-1$
+      }
+
+      builder.append(sqlUpdateAffix);
+      return builder.toString();
+    }
+
+    private int setUpdateAttributeValues(List<Pair<ITypeMapping, Object>> attributeChanges, PreparedStatement stmt,
+        int col) throws SQLException
+    {
+      for (Pair<ITypeMapping, Object> change : attributeChanges)
+      {
+        ITypeMapping typeMapping = change.getElement1();
+        Object value = change.getElement2();
+        if (typeMapping.getFeature().isUnsettable())
+        {
+          // feature is unsettable
+          if (value == null)
+          {
+            // feature is unset
+            typeMapping.setDefaultValue(stmt, col++);
+            stmt.setBoolean(col++, false);
+          }
+          else
+          {
+            // feature is set
+            typeMapping.setValue(stmt, col++, value);
+            stmt.setBoolean(col++, true);
+          }
+        }
+        else
+        {
+          typeMapping.setValue(stmt, col++, change.getElement2());
+        }
+      }
+
+      return col;
+    }
+
+    private int setUpdateListSizeChanges(List<Pair<EStructuralFeature, Integer>> attributeChanges,
+        PreparedStatement stmt, int col) throws SQLException
+    {
+      for (Pair<EStructuralFeature, Integer> change : listSizeChanges)
+      {
+        stmt.setInt(col++, change.getElement2());
+      }
+
+      return col;
+    }
+  }
+
+  @Override
+  protected void reviseOldRevision(IDBStoreAccessor accessor, CDOID id, CDOBranch branch, long timeStamp)
+  {
+    // do nothing
+  }
+
+  @Override
+  protected String getListXRefsWhere(QueryXRefsContext context)
+  {
+    if (CDORevision.UNSPECIFIED_DATE != context.getTimeStamp())
+    {
+      throw new IllegalArgumentException("Non-audit mode does not support timestamp specification");
+    }
+
+    if (!context.getBranch().isMainBranch())
+    {
+      throw new IllegalArgumentException("Non-audit mode does not support branch specification");
+    }
+
+    return CDODBSchema.ATTRIBUTES_REVISED + "=0";
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalNonAuditMappingStrategy.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalNonAuditMappingStrategy.java
new file mode 100644
index 0000000..d8f7f6e
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/HorizontalNonAuditMappingStrategy.java
@@ -0,0 +1,62 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - major refactoring
+ */
+package org.eclipse.emf.cdo.server.internal.db.mapping.horizontal;
+
+import org.eclipse.emf.cdo.server.db.mapping.IClassMapping;
+import org.eclipse.emf.cdo.server.db.mapping.IListMapping;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+/**
+ * @author Eike Stepper
+ * @since 2.0
+ */
+public class HorizontalNonAuditMappingStrategy extends AbstractHorizontalMappingStrategy
+{
+  public HorizontalNonAuditMappingStrategy()
+  {
+  }
+
+  public boolean hasAuditSupport()
+  {
+    return false;
+  }
+
+  public boolean hasBranchingSupport()
+  {
+    return false;
+  }
+
+  public boolean hasDeltaSupport()
+  {
+    return true;
+  }
+
+  @Override
+  public IListMapping doCreateListMapping(EClass containingClass, EStructuralFeature feature)
+  {
+    return new NonAuditListTableMapping(this, containingClass, feature);
+  }
+
+  @Override
+  public IListMapping doCreateFeatureMapMapping(EClass containingClass, EStructuralFeature feature)
+  {
+    return new NonAuditFeatureMapTableMapping(this, containingClass, feature);
+  }
+
+  @Override
+  protected IClassMapping doCreateClassMapping(EClass eClass)
+  {
+    return new HorizontalNonAuditClassMapping(this, eClass);
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/NonAuditFeatureMapTableMapping.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/NonAuditFeatureMapTableMapping.java
new file mode 100644
index 0000000..0f8c57e
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/NonAuditFeatureMapTableMapping.java
@@ -0,0 +1,590 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - 271444: [DB] Multiple refactorings bug 271444
+ *    Christopher Albert - 254455: [DB] Support FeatureMaps bug 254455
+ *    Stefan Winkler - Bug 329025: [DB] Support branching for range-based mapping strategy 
+ */
+package org.eclipse.emf.cdo.server.internal.db.mapping.horizontal;
+
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.delta.CDOAddFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOClearFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOContainerFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDeltaVisitor;
+import org.eclipse.emf.cdo.common.revision.delta.CDOListFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOMoveFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDORemoveFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOSetFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOUnsetFeatureDelta;
+import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
+import org.eclipse.emf.cdo.server.db.IIDHandler;
+import org.eclipse.emf.cdo.server.db.IPreparedStatementCache;
+import org.eclipse.emf.cdo.server.db.IPreparedStatementCache.ReuseProbability;
+import org.eclipse.emf.cdo.server.db.mapping.IListMappingDeltaSupport;
+import org.eclipse.emf.cdo.server.db.mapping.IMappingStrategy;
+import org.eclipse.emf.cdo.server.db.mapping.ITypeMapping;
+import org.eclipse.emf.cdo.server.internal.db.CDODBSchema;
+
+import org.eclipse.net4j.db.DBException;
+import org.eclipse.net4j.db.DBType;
+import org.eclipse.net4j.db.DBUtil;
+import org.eclipse.net4j.util.ImplementationError;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.util.FeatureMap;
+
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.Iterator;
+
+/**
+ * This is a featuremap-to-table mapping optimized for non-audit-mode. It doesn't care about version and has delta
+ * support.
+ * 
+ * @author Eike Stepper
+ * @since 3.0
+ */
+public class NonAuditFeatureMapTableMapping extends AbstractFeatureMapTableMapping implements IListMappingDeltaSupport
+{
+  private FieldInfo[] keyFields;
+
+  private static final int TEMP_INDEX = -1;
+
+  private static final int UNBOUNDED_MOVE = -1;
+
+  private String sqlClear;
+
+  private String sqlUpdateIndex;
+
+  private String sqlUpdateValue;
+
+  private String sqlDeleteItem;
+
+  private String sqlMoveDownWithLimit;
+
+  private String sqlMoveDown;
+
+  private String sqlMoveUpWithLimit;
+
+  private String sqlMoveUp;
+
+  public NonAuditFeatureMapTableMapping(IMappingStrategy mappingStrategy, EClass eClass, EStructuralFeature feature)
+  {
+    super(mappingStrategy, eClass, feature);
+    initSQLStrings();
+  }
+
+  private void initSQLStrings()
+  {
+    // TODO: add key fields length support
+
+    StringBuilder builder = new StringBuilder();
+
+    // ----------- clear list -------------------------
+
+    builder.append("DELETE FROM "); //$NON-NLS-1$
+    builder.append(getTable());
+    builder.append(" WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_REVISION_ID);
+    builder.append("=? "); //$NON-NLS-1$
+
+    sqlClear = builder.toString();
+
+    builder.append(" AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_IDX);
+    builder.append("=? "); //$NON-NLS-1$
+
+    sqlDeleteItem = builder.toString();
+
+    // ----------- update one item index --------------
+    builder = new StringBuilder();
+    builder.append("UPDATE "); //$NON-NLS-1$
+    builder.append(getTable());
+    builder.append(" SET "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_IDX);
+    builder.append("=? "); //$NON-NLS-1$
+    builder.append(" WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_REVISION_ID);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_IDX);
+    builder.append("=? "); //$NON-NLS-1$
+    sqlUpdateIndex = builder.toString();
+
+    // ----------- update one item value --------------
+    builder = new StringBuilder();
+    builder.append("UPDATE "); //$NON-NLS-1$
+    builder.append(getTable());
+    builder.append(" SET "); //$NON-NLS-1$
+
+    builder.append(CDODBSchema.FEATUREMAP_TAG);
+    builder.append("=?,"); //$NON-NLS-1$
+
+    Iterator<String> iter = getColumnNames().iterator();
+    while (iter.hasNext())
+    {
+      String column = iter.next();
+      builder.append(column);
+      builder.append("=?"); //$NON-NLS-1$
+
+      if (iter.hasNext())
+      {
+        builder.append(", "); //$NON-NLS-1$
+      }
+    }
+
+    builder.append(" WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_REVISION_ID);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_IDX);
+    builder.append("=? "); //$NON-NLS-1$
+    sqlUpdateValue = builder.toString();
+
+    // ----------- move down --------------
+    builder = new StringBuilder();
+    builder.append("UPDATE "); //$NON-NLS-1$
+    builder.append(getTable());
+    builder.append(" SET "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_IDX);
+    builder.append("="); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_IDX);
+    builder.append("-1 WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_REVISION_ID);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_IDX);
+    builder.append(">? "); //$NON-NLS-1$
+    sqlMoveDown = builder.toString();
+
+    builder.append(" AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_IDX);
+    builder.append("<=?"); //$NON-NLS-1$
+    sqlMoveDownWithLimit = builder.toString();
+
+    // ----------- move up --------------
+    builder = new StringBuilder();
+    builder.append("UPDATE "); //$NON-NLS-1$
+    builder.append(getTable());
+    builder.append(" SET "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_IDX);
+    builder.append("="); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_IDX);
+    builder.append("+1 WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_REVISION_ID);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_IDX);
+    builder.append(">=? "); //$NON-NLS-1$
+    sqlMoveUp = builder.toString();
+
+    builder.append(" AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.FEATUREMAP_IDX);
+    builder.append("<?"); //$NON-NLS-1$
+    sqlMoveUpWithLimit = builder.toString();
+  }
+
+  @Override
+  protected FieldInfo[] getKeyFields()
+  {
+    if (keyFields == null)
+    {
+      DBType dbType = getMappingStrategy().getStore().getIDHandler().getDBType();
+      keyFields = new FieldInfo[] { new FieldInfo(CDODBSchema.FEATUREMAP_REVISION_ID, dbType) };
+    }
+
+    return keyFields;
+  }
+
+  @Override
+  protected void setKeyFields(PreparedStatement stmt, CDORevision revision) throws SQLException
+  {
+    getMappingStrategy().getStore().getIDHandler().setCDOID(stmt, 1, revision.getID());
+  }
+
+  public void objectDetached(IDBStoreAccessor accessor, CDOID id, long revised)
+  {
+    clearList(accessor, id);
+  }
+
+  /**
+   * Clear a list of a given revision.
+   * 
+   * @param accessor
+   *          the accessor to use
+   * @param id
+   *          the id of the revision from which to remove all items
+   */
+  public void clearList(IDBStoreAccessor accessor, CDOID id)
+  {
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+
+    try
+    {
+      stmt = statementCache.getPreparedStatement(sqlClear, ReuseProbability.HIGH);
+      getMappingStrategy().getStore().getIDHandler().setCDOID(stmt, 1, id);
+      DBUtil.update(stmt, false);
+    }
+    catch (SQLException e)
+    {
+      throw new DBException(e);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  /**
+   * Insert a list item at a specified position.
+   * 
+   * @param accessor
+   *          the accessor to use
+   * @param id
+   *          the id of the revision to insert the value
+   * @param index
+   *          the index where to insert the element
+   * @param value
+   *          the value to insert.
+   */
+  public void insertListItem(IDBStoreAccessor accessor, CDOID id, int index, Object value, long timestamp)
+  {
+    move1up(accessor, id, index, UNBOUNDED_MOVE);
+    insertValue(accessor, id, index, value, timestamp);
+  }
+
+  private void insertValue(IDBStoreAccessor accessor, CDOID id, int index, Object value, long timestamp)
+  {
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+
+    try
+    {
+      FeatureMap.Entry entry = (FeatureMap.Entry)value;
+      EStructuralFeature entryFeature = entry.getEStructuralFeature();
+      CDOID tag = getTagByFeature(entryFeature, timestamp);
+      String columnName = getColumnName(tag);
+
+      String sql = sqlInsert;
+
+      stmt = statementCache.getPreparedStatement(sql, ReuseProbability.HIGH);
+
+      idHandler.setCDOID(stmt, 1, id);
+      int column = getKeyFields().length + 1;
+
+      for (int i = 0; i < getColumnNames().size(); i++)
+      {
+        if (getColumnNames().get(i).equals(columnName))
+        {
+          getTypeMapping(tag).setValue(stmt, column++, entry.getValue());
+        }
+        else
+        {
+          stmt.setNull(column++, getDBTypes().get(i).getCode());
+        }
+      }
+
+      stmt.setInt(column++, index);
+      idHandler.setCDOID(stmt, column++, tag);
+
+      DBUtil.update(stmt, true);
+    }
+    catch (SQLException e)
+    {
+      throw new DBException(e);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  /**
+   * Move a list item from one position to another. Indices between both positions are updated so that the list remains
+   * consistent.
+   * 
+   * @param accessor
+   *          the accessor to use
+   * @param id
+   *          the id of the revision in which to move the item
+   * @param oldPosition
+   *          the old position of the item.
+   * @param newPosition
+   *          the new position of the item.
+   */
+  public void moveListItem(IDBStoreAccessor accessor, CDOID id, int oldPosition, int newPosition)
+  {
+    if (oldPosition == newPosition)
+    {
+      return;
+    }
+
+    // move element away temporarily
+    updateOneIndex(accessor, id, oldPosition, TEMP_INDEX);
+
+    // move elements in between
+    if (oldPosition < newPosition)
+    {
+      move1down(accessor, id, oldPosition, newPosition);
+    }
+    else
+    {
+      // oldPosition > newPosition -- equal case is handled above
+      move1up(accessor, id, newPosition, oldPosition);
+    }
+
+    // move temporary element to new position
+    updateOneIndex(accessor, id, TEMP_INDEX, newPosition);
+  }
+
+  private void updateOneIndex(IDBStoreAccessor accessor, CDOID id, int oldIndex, int newIndex)
+  {
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+
+    try
+    {
+      stmt = statementCache.getPreparedStatement(sqlUpdateIndex, ReuseProbability.HIGH);
+      stmt.setInt(1, newIndex);
+      idHandler.setCDOID(stmt, 2, id);
+      stmt.setInt(3, oldIndex);
+      DBUtil.update(stmt, true);
+    }
+    catch (SQLException e)
+    {
+      throw new DBException(e);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  /**
+   * Remove a list item from a specified a position.
+   * 
+   * @param accessor
+   *          the accessor to use
+   * @param id
+   *          the id of the revision from which to remove the item
+   * @param index
+   *          the index of the item to remove
+   */
+  public void removeListItem(IDBStoreAccessor accessor, CDOID id, int index)
+  {
+    deleteItem(accessor, id, index);
+    move1down(accessor, id, index, UNBOUNDED_MOVE);
+  }
+
+  /**
+   * Move references downwards to close a gap at position <code>index</code>. Only indexes starting with
+   * <code>index + 1</code> and ending with <code>upperIndex</code> are moved down.
+   */
+  private void move1down(IDBStoreAccessor accessor, CDOID id, int index, int upperIndex)
+  {
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+
+    try
+    {
+      stmt = statementCache.getPreparedStatement(upperIndex == UNBOUNDED_MOVE ? sqlMoveDown : sqlMoveDownWithLimit,
+          ReuseProbability.HIGH);
+
+      idHandler.setCDOID(stmt, 1, id);
+      stmt.setInt(2, index);
+      if (upperIndex != UNBOUNDED_MOVE)
+      {
+        stmt.setInt(3, upperIndex);
+      }
+
+      DBUtil.update(stmt, false);
+    }
+    catch (SQLException e)
+    {
+      throw new DBException(e);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  /**
+   * Move references downwards to close a gap at position <code>index</code>. Only indexes starting with
+   * <code>index + 1</code> and ending with <code>upperIndex</code> are moved down.
+   */
+  private void move1up(IDBStoreAccessor accessor, CDOID id, int index, int upperIndex)
+  {
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+
+    try
+    {
+      stmt = statementCache.getPreparedStatement(upperIndex == UNBOUNDED_MOVE ? sqlMoveUp : sqlMoveUpWithLimit,
+          ReuseProbability.HIGH);
+      idHandler.setCDOID(stmt, 1, id);
+      stmt.setInt(2, index);
+      if (upperIndex != UNBOUNDED_MOVE)
+      {
+        stmt.setInt(3, upperIndex);
+      }
+
+      DBUtil.update(stmt, false);
+    }
+    catch (SQLException e)
+    {
+      throw new DBException(e);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  private void deleteItem(IDBStoreAccessor accessor, CDOID id, int index)
+  {
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+
+    try
+    {
+      stmt = statementCache.getPreparedStatement(sqlDeleteItem, ReuseProbability.HIGH);
+      idHandler.setCDOID(stmt, 1, id);
+      stmt.setInt(2, index);
+      DBUtil.update(stmt, true);
+    }
+    catch (SQLException e)
+    {
+      throw new DBException(e);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  /**
+   * Set a value at a specified position to the given value.
+   * 
+   * @param accessor
+   *          the accessor to use
+   * @param id
+   *          the id of the revision to set the value
+   * @param index
+   *          the index of the item to set
+   * @param value
+   *          the value to be set.
+   */
+  public void setListItem(IDBStoreAccessor accessor, CDOID id, int index, Object value, long timestamp)
+  {
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+
+    FeatureMap.Entry entry = (FeatureMap.Entry)value;
+    EStructuralFeature entryFeature = entry.getEStructuralFeature();
+    CDOID tag = getTagByFeature(entryFeature, timestamp);
+    String columnName = getColumnName(tag);
+    ITypeMapping mapping = getTypeMapping(tag);
+
+    try
+    {
+      stmt = statementCache.getPreparedStatement(sqlUpdateValue, ReuseProbability.HIGH);
+      idHandler.setCDOID(stmt, 1, tag);
+      int column = 2;
+
+      for (int i = 0; i < getColumnNames().size(); i++)
+      {
+        if (getColumnNames().get(i).equals(columnName))
+        {
+          mapping.setValue(stmt, column++, entry.getValue());
+        }
+        else
+        {
+          stmt.setNull(column++, getDBTypes().get(i).getCode());
+        }
+      }
+
+      idHandler.setCDOID(stmt, column++, id);
+      stmt.setInt(column++, index);
+      DBUtil.update(stmt, true);
+    }
+    catch (SQLException e)
+    {
+      throw new DBException(e);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  public void processDelta(final IDBStoreAccessor accessor, final CDOID id, final int branchId, int oldVersion,
+      final int newVersion, final long created, CDOListFeatureDelta listDelta)
+  {
+    CDOFeatureDeltaVisitor visitor = new CDOFeatureDeltaVisitor()
+    {
+      public void visit(CDOMoveFeatureDelta delta)
+      {
+        moveListItem(accessor, id, delta.getOldPosition(), delta.getNewPosition());
+      }
+
+      public void visit(CDOAddFeatureDelta delta)
+      {
+        insertListItem(accessor, id, delta.getIndex(), delta.getValue(), created);
+      }
+
+      public void visit(CDORemoveFeatureDelta delta)
+      {
+        removeListItem(accessor, id, delta.getIndex());
+      }
+
+      public void visit(CDOSetFeatureDelta delta)
+      {
+        setListItem(accessor, id, delta.getIndex(), delta.getValue(), created);
+      }
+
+      public void visit(CDOUnsetFeatureDelta delta)
+      {
+        if (delta.getFeature().isUnsettable())
+        {
+          throw new ImplementationError("Should not be called"); //$NON-NLS-1$
+        }
+
+        clearList(accessor, id);
+      }
+
+      public void visit(CDOListFeatureDelta delta)
+      {
+        throw new ImplementationError("Should not be called"); //$NON-NLS-1$
+      }
+
+      public void visit(CDOClearFeatureDelta delta)
+      {
+        clearList(accessor, id);
+      }
+
+      public void visit(CDOContainerFeatureDelta delta)
+      {
+        throw new ImplementationError("Should not be called"); //$NON-NLS-1$
+      }
+    };
+
+    for (CDOFeatureDelta delta : listDelta.getListChanges())
+    {
+      delta.accept(visitor);
+    }
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/NonAuditListTableMapping.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/NonAuditListTableMapping.java
new file mode 100644
index 0000000..92d96aa
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/NonAuditListTableMapping.java
@@ -0,0 +1,825 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - 271444: [DB] Multiple refactorings bug 271444
+ *    Stefan Winkler - Bug 329025: [DB] Support branching for range-based mapping strategy
+ */
+package org.eclipse.emf.cdo.server.internal.db.mapping.horizontal;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.delta.CDOAddFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOClearFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOContainerFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDeltaVisitor;
+import org.eclipse.emf.cdo.common.revision.delta.CDOListFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOMoveFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDORemoveFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOSetFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOUnsetFeatureDelta;
+import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
+import org.eclipse.emf.cdo.server.db.IIDHandler;
+import org.eclipse.emf.cdo.server.db.IPreparedStatementCache.ReuseProbability;
+import org.eclipse.emf.cdo.server.db.mapping.IListMappingDeltaSupport;
+import org.eclipse.emf.cdo.server.db.mapping.IMappingStrategy;
+import org.eclipse.emf.cdo.server.internal.db.CDODBSchema;
+import org.eclipse.emf.cdo.server.internal.db.bundle.OM;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+
+import org.eclipse.net4j.db.DBException;
+import org.eclipse.net4j.db.DBType;
+import org.eclipse.net4j.db.DBUtil;
+import org.eclipse.net4j.util.om.trace.ContextTracer;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+import org.eclipse.core.runtime.Assert;
+
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.ArrayList;
+
+/**
+ * This is a list-to-table mapping optimized for non-audit-mode. It doesn't care about version and has delta support.
+ * 
+ * @author Eike Stepper
+ * @since 2.0
+ */
+public class NonAuditListTableMapping extends AbstractListTableMapping implements IListMappingDeltaSupport
+{
+  private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG, NonAuditListTableMapping.class);
+
+  private FieldInfo[] keyFields;
+
+  private static final int UNBOUNDED_SHIFT = -1;
+
+  /**
+   * The central data structure which is used to calculate the outcomes of the list deltas.
+   */
+  private ArrayList<ManipulationElement> manipulations = new ArrayList<ManipulationElement>();
+
+  /**
+   * This is a flag to remember if a delta of type "clear" has been encountered. If so, the list in the DB has to be
+   * cleared before writing out the changes.
+   */
+  private boolean clearFirst;
+
+  private String sqlClear;
+
+  private String sqlUpdateValue;
+
+  private String sqlUpdateIndex;
+
+  private String sqlInsertValue;
+
+  private String sqlDeleteItem;
+
+  public NonAuditListTableMapping(IMappingStrategy mappingStrategy, EClass eClass, EStructuralFeature feature)
+  {
+    super(mappingStrategy, eClass, feature);
+    initSQLStrings();
+  }
+
+  private void initSQLStrings()
+  {
+    // ----------- clear list -------------------------
+    StringBuilder builder = new StringBuilder();
+
+    builder.append("DELETE FROM "); //$NON-NLS-1$
+    builder.append(getTable());
+    builder.append(" WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_ID);
+    builder.append("=? "); //$NON-NLS-1$
+
+    sqlClear = builder.toString();
+
+    builder.append(" AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_IDX);
+    builder.append("=? "); //$NON-NLS-1$
+
+    sqlDeleteItem = builder.toString();
+
+    // ----------- update one item --------------------
+    builder = new StringBuilder();
+    builder.append("UPDATE "); //$NON-NLS-1$
+    builder.append(getTable());
+    builder.append(" SET "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_VALUE);
+    builder.append("=? "); //$NON-NLS-1$
+    builder.append(" WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_ID);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_IDX);
+    builder.append("=? "); //$NON-NLS-1$
+    sqlUpdateValue = builder.toString();
+
+    // ----------- insert one item --------------------
+    builder = new StringBuilder();
+    builder.append("INSERT INTO "); //$NON-NLS-1$
+    builder.append(getTable());
+    builder.append(" ("); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_ID);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_IDX);
+    builder.append(", "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_VALUE);
+    builder.append(") VALUES(?, ?, ?) "); //$NON-NLS-1$
+    sqlInsertValue = builder.toString();
+
+    // ----------- update one item index --------------
+    builder = new StringBuilder();
+    builder.append("UPDATE "); //$NON-NLS-1$
+    builder.append(getTable());
+    builder.append(" SET "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_IDX);
+    builder.append("=? "); //$NON-NLS-1$
+    builder.append(" WHERE "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_REVISION_ID);
+    builder.append("=? AND "); //$NON-NLS-1$
+    builder.append(CDODBSchema.LIST_IDX);
+    builder.append("=? "); //$NON-NLS-1$
+    sqlUpdateIndex = builder.toString();
+  }
+
+  @Override
+  protected FieldInfo[] getKeyFields()
+  {
+    if (keyFields == null)
+    {
+      DBType dbType = getMappingStrategy().getStore().getIDHandler().getDBType();
+      keyFields = new FieldInfo[] { new FieldInfo(CDODBSchema.LIST_REVISION_ID, dbType) };
+    }
+
+    return keyFields;
+  }
+
+  @Override
+  protected void setKeyFields(PreparedStatement stmt, CDORevision revision) throws SQLException
+  {
+    getMappingStrategy().getStore().getIDHandler().setCDOID(stmt, 1, revision.getID());
+  }
+
+  public void objectDetached(IDBStoreAccessor accessor, CDOID id, long revised)
+  {
+    clearList(accessor, id);
+  }
+
+  /**
+   * Clear a list of a given revision.
+   * 
+   * @param accessor
+   *          the accessor to use
+   * @param id
+   *          the id of the revision from which to remove all items
+   */
+  public void clearList(IDBStoreAccessor accessor, CDOID id)
+  {
+    PreparedStatement stmt = null;
+
+    try
+    {
+      stmt = accessor.getStatementCache().getPreparedStatement(sqlClear, ReuseProbability.HIGH);
+      getMappingStrategy().getStore().getIDHandler().setCDOID(stmt, 1, id);
+      DBUtil.update(stmt, false);
+    }
+    catch (SQLException e)
+    {
+      throw new DBException(e);
+    }
+    finally
+    {
+      accessor.getStatementCache().releasePreparedStatement(stmt);
+    }
+  }
+
+  public void processDelta(final IDBStoreAccessor accessor, final CDOID id, int branchId, int oldVersion,
+      final int newVersion, long created, CDOListFeatureDelta delta)
+  {
+    CDOBranchPoint main = accessor.getStore().getRepository().getBranchManager().getMainBranch().getHead();
+
+    InternalCDORevision originalRevision = (InternalCDORevision)accessor.getStore().getRepository()
+        .getRevisionManager().getRevision(id, main, CDORevision.UNCHUNKED, CDORevision.DEPTH_NONE, true);
+    int oldListSize = originalRevision.getList(getFeature()).size();
+
+    // reset the clear-flag
+    clearFirst = false;
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("ListTableMapping.processDelta for revision {0} - previous list size: {1}", originalRevision, //$NON-NLS-1$
+          oldListSize);
+    }
+
+    if (manipulations == null)
+    {
+      manipulations = new ArrayList<ManipulationElement>();
+    }
+    else
+    {
+      manipulations.clear();
+    }
+
+    // create list and initialize with original indexes
+    for (int i = 0; i < oldListSize; i++)
+    {
+      manipulations.add(createOriginalElement(i));
+    }
+
+    // let the visitor collect the changes
+    ListDeltaVisitor visitor = new ListDeltaVisitor();
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Procssing deltas..."); //$NON-NLS-1$
+    }
+
+    for (CDOFeatureDelta listDelta : delta.getListChanges())
+    {
+      listDelta.accept(visitor);
+    }
+
+    // TODO: here, we could implement further optimizations.
+    // e.g., if more than 50% of the list's items are removed,
+    // it's better to clear the list and reinsert all values
+    // from scratch.
+
+    // finally, write results to the database
+    writeResultToDatabase(accessor, id);
+  }
+
+  /**
+   * Write calculated changes to the database
+   * 
+   * @param accessor
+   *          ,
+   */
+  private void writeResultToDatabase(IDBStoreAccessor accessor, CDOID id)
+  {
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    PreparedStatement deleteStmt = null;
+    PreparedStatement moveStmt = null;
+    PreparedStatement setValueStmt = null;
+    PreparedStatement insertStmt = null;
+
+    int deleteCounter = 0;
+    int moveCounter = 0;
+    int setValueCounter = 0;
+    int insertCounter = 0;
+
+    int tempIndex = -1;
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Writing to database:"); //$NON-NLS-1$
+    }
+
+    if (clearFirst)
+    {
+      if (TRACER.isEnabled())
+      {
+        TRACER.format(" - clear list"); //$NON-NLS-1$
+      }
+
+      clearList(accessor, id);
+    }
+
+    try
+    {
+      for (ManipulationElement element : manipulations)
+      {
+        if (element.is(ManipulationConstants.DELETE))
+        {
+          /*
+           * Step 1: DELETE all elements e which have e.is(REMOVE) by e.sourceIdx
+           */
+
+          if (deleteStmt == null)
+          {
+            deleteStmt = accessor.getStatementCache().getPreparedStatement(sqlDeleteItem, ReuseProbability.HIGH);
+            idHandler.setCDOID(deleteStmt, 1, id);
+          }
+
+          deleteStmt.setInt(2, element.sourceIndex);
+          deleteStmt.addBatch();
+          deleteCounter++;
+
+          if (TRACER.isEnabled())
+          {
+            TRACER.format(" - delete at {0} ", element.sourceIndex); //$NON-NLS-1$
+          }
+        }
+
+        if (element.is(ManipulationConstants.MOVE))
+        {
+          /*
+           * Step 2: MOVE all elements e (by e.sourceIdx) which have e.is(MOVE) to temporary idx (-1, -2, -3, -4, ...)
+           * and store temporary idx in e.tempIndex
+           */
+          if (moveStmt == null)
+          {
+            moveStmt = accessor.getStatementCache().getPreparedStatement(sqlUpdateIndex, ReuseProbability.HIGH);
+            idHandler.setCDOID(moveStmt, 2, id);
+          }
+
+          moveStmt.setInt(3, element.sourceIndex); // from index
+          moveStmt.setInt(1, --tempIndex); // to index
+          element.tempIndex = tempIndex;
+          moveStmt.addBatch();
+          moveCounter++;
+
+          if (TRACER.isEnabled())
+          {
+            TRACER.format(" - move {0} -> {1} ", element.sourceIndex, element.tempIndex); //$NON-NLS-1$
+          }
+        }
+      }
+
+      /*
+       * Step 3: move all elements which have to be shifted up or down because of add, remove or move of other elements
+       * to their proper position. This has to be done in two phases to avoid collisions, as the index has to be unique
+       */
+      int size = manipulations.size();
+
+      /* Step 3a: shift down */
+      for (int i = 0; i < size; i++)
+      {
+        ManipulationElement element = manipulations.get(i);
+
+        if ((element.type == ManipulationConstants.NONE || element.type == ManipulationConstants.SET_VALUE)
+            && element.sourceIndex > element.destinationIndex)
+        {
+          if (moveStmt == null)
+          {
+            moveStmt = accessor.getStatementCache().getPreparedStatement(sqlUpdateIndex, ReuseProbability.HIGH);
+            idHandler.setCDOID(moveStmt, 2, id);
+          }
+
+          moveStmt.setInt(3, element.sourceIndex); // from index
+          moveStmt.setInt(1, element.destinationIndex); // to index
+          moveStmt.addBatch();
+          moveCounter++;
+          if (TRACER.isEnabled())
+          {
+            TRACER.format(" - move {0} -> {1} ", element.sourceIndex, element.destinationIndex); //$NON-NLS-1$
+          }
+        }
+      }
+
+      /* Step 3b: shift up */
+      for (int i = size - 1; i >= 0; i--)
+      {
+        ManipulationElement element = manipulations.get(i);
+
+        if ((element.type == ManipulationConstants.NONE || element.type == ManipulationConstants.SET_VALUE)
+            && element.sourceIndex < element.destinationIndex)
+        {
+          if (moveStmt == null)
+          {
+            moveStmt = accessor.getStatementCache().getPreparedStatement(sqlUpdateIndex, ReuseProbability.HIGH);
+            idHandler.setCDOID(moveStmt, 2, id);
+          }
+
+          moveStmt.setInt(3, element.sourceIndex); // from index
+          moveStmt.setInt(1, element.destinationIndex); // to index
+          moveStmt.addBatch();
+          moveCounter++;
+          if (TRACER.isEnabled())
+          {
+            TRACER.format(" - move {0} -> {1} ", element.sourceIndex, element.destinationIndex); //$NON-NLS-1$
+          }
+        }
+      }
+
+      for (ManipulationElement element : manipulations)
+      {
+        if (element.is(ManipulationConstants.MOVE))
+        {
+          /*
+           * Step 4: MOVE all elements e have e.is(MOVE) from e.tempIdx to e.destinationIdx (because we have moved them
+           * before, moveStmt is always initialized
+           */
+          moveStmt.setInt(3, element.tempIndex); // from index
+          moveStmt.setInt(1, element.destinationIndex); // to index
+          element.tempIndex = tempIndex;
+          moveStmt.addBatch();
+          moveCounter++;
+
+          if (TRACER.isEnabled())
+          {
+            TRACER.format(" - move {0} -> {1} ", element.tempIndex, element.destinationIndex); //$NON-NLS-1$
+          }
+        }
+
+        if (element.is(ManipulationConstants.SET_VALUE))
+        {
+          /*
+           * Step 5: SET all elements which have e.type == SET_VALUE by index == e.destinationIdx
+           */
+          if (setValueStmt == null)
+          {
+            setValueStmt = accessor.getStatementCache().getPreparedStatement(sqlUpdateValue, ReuseProbability.HIGH);
+            idHandler.setCDOID(setValueStmt, 2, id);
+          }
+
+          setValueStmt.setInt(3, element.destinationIndex);
+          getTypeMapping().setValue(setValueStmt, 1, element.value);
+          setValueStmt.addBatch();
+          setValueCounter++;
+
+          if (TRACER.isEnabled())
+          {
+            TRACER.format(" - set value at {0} to {1} ", element.destinationIndex, element.value); //$NON-NLS-1$
+          }
+        }
+
+        if (element.is(ManipulationConstants.INSERT))
+        {
+          /*
+           * Step 6: INSERT all elements which have e.type == INSERT.
+           */
+          if (insertStmt == null)
+          {
+            insertStmt = accessor.getStatementCache().getPreparedStatement(sqlInsertValue, ReuseProbability.HIGH);
+            idHandler.setCDOID(insertStmt, 1, id);
+          }
+
+          insertStmt.setInt(2, element.destinationIndex);
+          getTypeMapping().setValue(insertStmt, 3, element.value);
+          insertStmt.addBatch();
+          insertCounter++;
+
+          if (TRACER.isEnabled())
+          {
+            TRACER.format(" - insert value at {0} : value {1} ", element.destinationIndex, element.value); //$NON-NLS-1$
+          }
+        }
+      }
+
+      // finally perform all operations
+      if (deleteCounter > 0)
+      {
+        if (TRACER.isEnabled())
+        {
+          TRACER.format("Performing {0} delete operations", deleteCounter); //$NON-NLS-1$
+        }
+
+        DBUtil.executeBatch(deleteStmt, deleteCounter);
+      }
+
+      if (moveCounter > 0)
+      {
+        if (TRACER.isEnabled())
+        {
+          TRACER.format("Performing {0} move operations", moveCounter); //$NON-NLS-1$
+        }
+
+        DBUtil.executeBatch(moveStmt, moveCounter);
+      }
+
+      if (insertCounter > 0)
+      {
+        if (TRACER.isEnabled())
+        {
+          TRACER.format("Performing {0} insert operations", insertCounter); //$NON-NLS-1$
+        }
+
+        DBUtil.executeBatch(insertStmt, insertCounter);
+      }
+
+      if (setValueCounter > 0)
+      {
+        if (TRACER.isEnabled())
+        {
+          TRACER.format("Performing {0} set operations", setValueCounter); //$NON-NLS-1$
+        }
+
+        DBUtil.executeBatch(setValueStmt, setValueCounter);
+      }
+    }
+    catch (SQLException e)
+    {
+      throw new DBException(e);
+    }
+    finally
+    {
+      releaseStatement(accessor, deleteStmt, moveStmt, insertStmt, setValueStmt);
+    }
+  }
+
+  private void releaseStatement(IDBStoreAccessor accessor, PreparedStatement... stmts)
+  {
+    Throwable t = null;
+
+    for (PreparedStatement stmt : stmts)
+    {
+      try
+      {
+        if (stmt != null)
+        {
+          try
+          {
+            stmt.clearBatch();
+          }
+          catch (SQLException e)
+          {
+            throw new DBException(e);
+          }
+          finally
+          {
+            accessor.getStatementCache().releasePreparedStatement(stmt);
+          }
+        }
+      }
+      catch (Throwable th)
+      {
+        if (t == null)
+        {
+          // remember first exception
+          t = th;
+        }
+
+        // more exceptions go to the log
+        OM.LOG.error(t);
+      }
+    }
+
+    if (t != null)
+    {
+      throw new DBException(t);
+    }
+  }
+
+  /**
+   * Helper method: shift all (destination) indexes in the interval [from,to] (inclusive at both ends) by offset
+   * (positive or negative).
+   */
+  private void shiftIndexes(int from, int to, int offset)
+  {
+    for (ManipulationElement e : manipulations)
+    {
+      if (e.destinationIndex >= from && (to == UNBOUNDED_SHIFT || e.destinationIndex <= to))
+      {
+        e.destinationIndex += offset;
+      }
+    }
+  }
+
+  /**
+   * Find a manipulation item by destination index).
+   */
+  private ManipulationElement findElement(int index)
+  {
+    for (ManipulationElement e : manipulations)
+    {
+      if (e.destinationIndex == index)
+      {
+        return e;
+      }
+    }
+
+    // never reached
+    Assert.isTrue(false);
+    return null;
+  }
+
+  /**
+   * Delete an element (used in remove and clear)
+   */
+  private void deleteItem(ManipulationElement e)
+  {
+    if (e.is(ManipulationConstants.INSERT))
+    {
+      // newly inserted items are simply removed, as
+      // removing inserted items is equal to no change at all.
+      manipulations.remove(e);
+    }
+    else
+    {
+      // mark the existing item as to be deleted.
+      // (previous MOVE and SET conditions are overridden by setting
+      // the exclusive DELETE type).
+      e.type = ManipulationConstants.DELETE;
+      e.destinationIndex = ManipulationConstants.NO_INDEX;
+    }
+  }
+
+  /**
+   * Create a ManipulationElement which represents an element which already is in the list.
+   */
+  private ManipulationElement createOriginalElement(int index)
+  {
+    return new ManipulationElement(index, index, ManipulationConstants.NIL, ManipulationConstants.NONE);
+  }
+
+  /**
+   * Create a ManipulationElement which represents an element which is inserted in the list.
+   */
+  private ManipulationElement createInsertedElement(int index, Object value)
+  {
+    return new ManipulationElement(ManipulationConstants.NONE, index, value, ManipulationConstants.INSERT);
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  private final class ListDeltaVisitor implements CDOFeatureDeltaVisitor
+  {
+    public void visit(CDOAddFeatureDelta delta)
+    {
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("  - insert at {0} value {1}", delta.getIndex(), delta.getValue()); //$NON-NLS-1$
+      }
+
+      // make room for the new item
+      shiftIndexes(delta.getIndex(), UNBOUNDED_SHIFT, +1);
+
+      // create the item
+      manipulations.add(createInsertedElement(delta.getIndex(), delta.getValue()));
+    }
+
+    public void visit(CDORemoveFeatureDelta delta)
+    {
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("  - remove at {0}", delta.getIndex()); //$NON-NLS-1$
+      }
+
+      ManipulationElement e = findElement(delta.getIndex());
+      deleteItem(e);
+
+      // fill the gap by shifting all subsequent items down
+      shiftIndexes(delta.getIndex() + 1, UNBOUNDED_SHIFT, -1);
+    }
+
+    public void visit(CDOSetFeatureDelta delta)
+    {
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("  - set at {0} value {1}", delta.getIndex(), delta.getValue()); //$NON-NLS-1$
+      }
+
+      ManipulationElement e = findElement(delta.getIndex());
+      // set the new value
+      e.value = delta.getValue();
+
+      // if the item is freshly inserted we do not set the SET-mark.
+      // setting the value of a new item results in inserting with the
+      // new value at once.
+      if (!e.is(ManipulationConstants.INSERT))
+      {
+        // else mark the existing item to be set to a new value
+        e.addType(ManipulationConstants.SET_VALUE);
+      }
+    }
+
+    public void visit(CDOClearFeatureDelta delta)
+    {
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("  - clear list"); //$NON-NLS-1$
+      }
+
+      // set the clear-flag
+      clearFirst = true;
+
+      // and also clear all manipulation items
+      manipulations.clear();
+    }
+
+    public void visit(CDOMoveFeatureDelta delta)
+    {
+      int fromIdx = delta.getOldPosition();
+      int toIdx = delta.getNewPosition();
+
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("  - move {0} -> {1}", fromIdx, toIdx); //$NON-NLS-1$
+      }
+
+      // ignore the trivial case
+      if (fromIdx == toIdx)
+      {
+        return;
+      }
+
+      ManipulationElement e = findElement(fromIdx);
+
+      // adjust indexes and shift either up or down
+      if (fromIdx < toIdx)
+      {
+        shiftIndexes(fromIdx + 1, toIdx, -1);
+      }
+      else
+      { // fromIdx > toIdx here
+        shiftIndexes(toIdx, fromIdx - 1, +1);
+      }
+
+      // set the new index
+      e.destinationIndex = toIdx;
+
+      // if it is a new element, no MOVE mark needed, because we insert it
+      // at the new position
+      if (!e.is(ManipulationConstants.INSERT))
+      {
+        // else we need to handle the move of an existing item
+        e.addType(ManipulationConstants.MOVE);
+      }
+    }
+
+    public void visit(CDOUnsetFeatureDelta delta)
+    {
+      if (delta.getFeature().isUnsettable())
+      {
+        Assert.isTrue(false);
+      }
+
+      if (TRACER.isEnabled())
+      {
+        TRACER.format("  - unset list"); //$NON-NLS-1$
+      }
+
+      // set the clear-flag
+      clearFirst = true;
+
+      // and also clear all manipulation items
+      manipulations.clear();
+    }
+
+    public void visit(CDOListFeatureDelta delta)
+    {
+      // never called
+      Assert.isTrue(false);
+    }
+
+    public void visit(CDOContainerFeatureDelta delta)
+    {
+      // never called
+      Assert.isTrue(false);
+    }
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  private static final class ManipulationConstants
+  {
+    public static final int NO_INDEX = Integer.MIN_VALUE;
+
+    public static final int DELETE = 1 << 4;
+
+    public static final int INSERT = 1 << 3;
+
+    public static final int MOVE = 1 << 2;
+
+    public static final int SET_VALUE = 1 << 1;
+
+    public static final Object NIL = new Object();
+
+    public static final int NONE = 0;
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  private static final class ManipulationElement
+  {
+    public int type;
+
+    public int sourceIndex;
+
+    public int tempIndex;
+
+    public int destinationIndex;
+
+    public Object value;
+
+    public ManipulationElement(int srcIdx, int dstIdx, Object val, int t)
+    {
+      sourceIndex = srcIdx;
+      tempIndex = ManipulationConstants.NONE;
+      destinationIndex = dstIdx;
+      value = val;
+      type = t;
+    }
+
+    public boolean is(int t)
+    {
+      return (type & t) > 0;
+    }
+
+    public void addType(int t)
+    {
+      type |= t;
+    }
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/ObjectTypeCache.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/ObjectTypeCache.java
new file mode 100644
index 0000000..5f38c81
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/ObjectTypeCache.java
@@ -0,0 +1,98 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server.internal.db.mapping.horizontal;
+
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
+import org.eclipse.emf.cdo.server.db.IIDHandler;
+
+import java.sql.Connection;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * @author Eike Stepper
+ * @since 4.0
+ */
+public class ObjectTypeCache extends DelegatingObjectTypeMapper
+{
+  public static final int DEFAULT_CACHE_CAPACITY = 100000;
+
+  private Map<CDOID, CDOID> memoryCache;
+
+  private int cacheSize;
+
+  public ObjectTypeCache(int cacheSize)
+  {
+    this.cacheSize = cacheSize;
+  }
+
+  @Override
+  protected CDOID doGetObjectType(IDBStoreAccessor accessor, CDOID id)
+  {
+    return memoryCache.get(id);
+  }
+
+  @Override
+  protected void doPutObjectType(IDBStoreAccessor accessor, CDOID id, CDOID type)
+  {
+    memoryCache.put(id, type);
+  }
+
+  @Override
+  protected void doRemoveObjectType(IDBStoreAccessor accessor, CDOID id)
+  {
+    memoryCache.remove(id);
+  }
+
+  @Override
+  protected CDOID doGetMaxID(Connection connection, IIDHandler idHandler)
+  {
+    return null;
+  }
+
+  @Override
+  protected void doActivate() throws Exception
+  {
+    super.doActivate();
+    memoryCache = Collections.synchronizedMap(new MemoryCache(cacheSize));
+  }
+
+  @Override
+  protected void doDeactivate() throws Exception
+  {
+    memoryCache = null;
+    super.doDeactivate();
+  }
+
+  /**
+   * @author Stefan Winkler
+   */
+  private static final class MemoryCache extends LinkedHashMap<CDOID, CDOID>
+  {
+    private static final long serialVersionUID = 1L;
+
+    private int capacity;
+
+    public MemoryCache(int capacity)
+    {
+      super(capacity, 0.75f, true);
+      this.capacity = capacity;
+    }
+
+    @Override
+    protected boolean removeEldestEntry(java.util.Map.Entry<CDOID, CDOID> eldest)
+    {
+      return size() > capacity;
+    }
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/ObjectTypeTable.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/ObjectTypeTable.java
new file mode 100644
index 0000000..c1b5754
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/ObjectTypeTable.java
@@ -0,0 +1,256 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - bug 259402
+ *    Stefan Winkler - redesign (prepared statements)
+ *    Stefan Winkler - bug 276926
+ */
+package org.eclipse.emf.cdo.server.internal.db.mapping.horizontal;
+
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.model.CDOClassifierRef;
+import org.eclipse.emf.cdo.common.protocol.CDODataInput;
+import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
+import org.eclipse.emf.cdo.server.db.IDBStore;
+import org.eclipse.emf.cdo.server.db.IDBStoreAccessor;
+import org.eclipse.emf.cdo.server.db.IIDHandler;
+import org.eclipse.emf.cdo.server.db.IPreparedStatementCache;
+import org.eclipse.emf.cdo.server.db.IPreparedStatementCache.ReuseProbability;
+import org.eclipse.emf.cdo.server.internal.db.CDODBSchema;
+
+import org.eclipse.net4j.db.DBException;
+import org.eclipse.net4j.db.DBType;
+import org.eclipse.net4j.db.DBUtil;
+import org.eclipse.net4j.db.IDBAdapter;
+import org.eclipse.net4j.db.ddl.IDBField;
+import org.eclipse.net4j.db.ddl.IDBIndex;
+import org.eclipse.net4j.db.ddl.IDBSchema;
+import org.eclipse.net4j.db.ddl.IDBTable;
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+
+import org.eclipse.emf.ecore.EClass;
+
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+/**
+ * @author Eike Stepper
+ * @since 4.0
+ */
+public class ObjectTypeTable extends AbstractObjectTypeMapper
+{
+  private IDBTable table;
+
+  private IDBField idField;
+
+  private IDBField typeField;
+
+  private IDBField timeField;
+
+  private String sqlDelete;
+
+  private String sqlInsert;
+
+  private String sqlSelect;
+
+  public ObjectTypeTable()
+  {
+  }
+
+  public final CDOClassifierRef getObjectType(IDBStoreAccessor accessor, CDOID id)
+  {
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+
+    try
+    {
+      stmt = statementCache.getPreparedStatement(sqlSelect, ReuseProbability.MAX);
+      idHandler.setCDOID(stmt, 1, id);
+      DBUtil.trace(stmt.toString());
+      ResultSet resultSet = stmt.executeQuery();
+
+      if (!resultSet.next())
+      {
+        DBUtil.trace("ClassID for CDOID " + id + " not found"); //$NON-NLS-1$ //$NON-NLS-2$
+        return null;
+      }
+
+      CDOID classID = idHandler.getCDOID(resultSet, 1);
+      EClass eClass = (EClass)getMetaDataManager().getMetaInstance(classID);
+      return new CDOClassifierRef(eClass);
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  public final void putObjectType(IDBStoreAccessor accessor, long timeStamp, CDOID id, EClass type)
+  {
+    IDBStore store = getMappingStrategy().getStore();
+    IIDHandler idHandler = store.getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+
+    try
+    {
+      stmt = statementCache.getPreparedStatement(sqlInsert, ReuseProbability.MAX);
+      idHandler.setCDOID(stmt, 1, id);
+      idHandler.setCDOID(stmt, 2, getMetaDataManager().getMetaID(type, timeStamp));
+      stmt.setLong(3, timeStamp);
+      DBUtil.trace(stmt.toString());
+      int result = stmt.executeUpdate();
+
+      if (result != 1)
+      {
+        throw new DBException("Object type could not be inserted: " + id); //$NON-NLS-1$
+      }
+    }
+    catch (SQLException ex)
+    {
+      // Unique key violation can occur in rare cases (merging new objects from other branches)
+      if (!store.getDBAdapter().isDuplicateKeyException(ex))
+      {
+        throw new DBException(ex);
+      }
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  public final void removeObjectType(IDBStoreAccessor accessor, CDOID id)
+  {
+    IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+    IPreparedStatementCache statementCache = accessor.getStatementCache();
+    PreparedStatement stmt = null;
+
+    try
+    {
+      stmt = statementCache.getPreparedStatement(sqlDelete, ReuseProbability.MAX);
+      idHandler.setCDOID(stmt, 1, id);
+      DBUtil.trace(stmt.toString());
+      int result = stmt.executeUpdate();
+
+      if (result != 1)
+      {
+        throw new DBException("Object type could not be deleted: " + id); //$NON-NLS-1$
+      }
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex);
+    }
+    finally
+    {
+      statementCache.releasePreparedStatement(stmt);
+    }
+  }
+
+  public CDOID getMaxID(Connection connection, IIDHandler idHandler)
+  {
+    Statement stmt = null;
+    ResultSet resultSet = null;
+
+    try
+    {
+      stmt = connection.createStatement();
+      resultSet = stmt.executeQuery("SELECT MAX(" + idField + ") FROM " + table);
+
+      if (resultSet.next())
+      {
+        return idHandler.getCDOID(resultSet, 1);
+      }
+
+      return null;
+    }
+    catch (SQLException ex)
+    {
+      throw new DBException(ex);
+    }
+    finally
+    {
+      DBUtil.close(resultSet);
+      DBUtil.close(stmt);
+    }
+  }
+
+  public void rawExport(Connection connection, CDODataOutput out, long fromCommitTime, long toCommitTime)
+      throws IOException
+  {
+    String where = " WHERE " + timeField + " BETWEEN " + fromCommitTime + " AND " + toCommitTime;
+    DBUtil.serializeTable(out, connection, table, null, where);
+  }
+
+  public void rawImport(Connection connection, CDODataInput in, OMMonitor monitor) throws IOException
+  {
+    DBUtil.deserializeTable(in, connection, table, monitor);
+  }
+
+  @Override
+  protected void doActivate() throws Exception
+  {
+    super.doActivate();
+
+    IDBStore store = getMappingStrategy().getStore();
+    IDBSchema schema = store.getDBSchema();
+    DBType dbType = store.getIDHandler().getDBType();
+
+    table = schema.addTable(CDODBSchema.CDO_OBJECTS);
+    idField = table.addField(CDODBSchema.ATTRIBUTES_ID, dbType);
+    typeField = table.addField(CDODBSchema.ATTRIBUTES_CLASS, dbType);
+    timeField = table.addField(CDODBSchema.ATTRIBUTES_CREATED, DBType.BIGINT);
+    table.addIndex(IDBIndex.Type.UNIQUE, idField);
+
+    IDBAdapter dbAdapter = store.getDBAdapter();
+    IDBStoreAccessor writer = store.getWriter(null);
+    Connection connection = writer.getConnection();
+    Statement statement = null;
+
+    try
+    {
+      statement = connection.createStatement();
+      dbAdapter.createTable(table, statement);
+      connection.commit();
+    }
+    catch (SQLException ex)
+    {
+      connection.rollback();
+      throw new DBException(ex);
+    }
+    finally
+    {
+      DBUtil.close(statement);
+      writer.release();
+    }
+
+    sqlSelect = "SELECT " + typeField + " FROM " + table + " WHERE " + idField + "=?"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+    sqlInsert = "INSERT INTO " + table + "(" + idField + "," + typeField + "," + timeField + ") VALUES (?, ?, ?)";
+    sqlDelete = "DELETE FROM " + table + " WHERE " + idField + "=?"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+  }
+
+  @Override
+  protected void doDeactivate() throws Exception
+  {
+    table = null;
+    idField = null;
+    typeField = null;
+    super.doDeactivate();
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/messages/Messages.java b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/messages/Messages.java
new file mode 100644
index 0000000..a60fb5d
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/messages/Messages.java
@@ -0,0 +1,41 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *    Victor Roldan Betancort - initial API and implementation
+ *    Eike Stepper - maintenance
+ */
+package org.eclipse.emf.cdo.server.internal.db.messages;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+/**
+ * @author Victor Roldan Betancort
+ */
+public class Messages
+{
+  private static final String BUNDLE_NAME = "org.eclipse.emf.cdo.server.internal.db.messages.messages"; //$NON-NLS-1$
+
+  private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle(BUNDLE_NAME);
+
+  private Messages()
+  {
+  }
+
+  public static String getString(String key)
+  {
+    try
+    {
+      return RESOURCE_BUNDLE.getString(key);
+    }
+    catch (MissingResourceException e)
+    {
+      return '!' + key + '!';
+    }
+  }
+}
diff --git a/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/messages/messages.properties b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/messages/messages.properties
new file mode 100644
index 0000000..e6baaa8
--- /dev/null
+++ b/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/messages/messages.properties
@@ -0,0 +1,31 @@
+# Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#    Victor Roldan Betancort - initial API and implementation
+#    Eike Stepper - maintenance
+#    Stefan Winkler - Bug 285426: [DB] Implement user-defined typeMapping support
+
+DBStore.0=dbConnectionProvider is null
+DBStore.1=dbAdapter is null
+DBStore.2=mappingStrategy is null
+DBStore.3=idHandler is null
+DBStore.9=Detected crash of repository {0}
+DBStore.10=Repaired crash of repository {0}: lastObjectID={1}, nextLocalObjectID={2}, lastBranchID={3}, lastCommitTime={4}, lastNonLocalCommitTime={5}
+DBStore.10b=Repaired crash of repository {0}: lastBranchID={1}, lastCommitTime={2}, lastNonLocalCommitTime={3}
+DBStore.11=Repairing crash of repository {0} failed.
+
+
+TypeMappingRegistry.1=No type mapping factory found for {0}: {1} --> DBType.{2}
+TypeMappingRegistry.2=TypeMapping {0} annotated at feature {1} could not be found in registry.
+TypeMappingRegistry.3=Runtime removal of ITypeMapping.Factory extensions is currently not supported.
+TypeMappingRegistry.4=Duplicate source:target typeMapping pairs are currently not supported!
+TypeMappingRegistry.5=Duplicate typeMapping ID: {0}
+
+FactoryTypeParserException.1=Invalid format for typeMapping factoryType {0}
+FactoryTypeParserException.2=EPackage {0} could not be resolved while registering typeMapping factoryType {1}
+FactoryTypeParserException.3=EClassifier {0} could not be resolved while registering typeMapping factoryType {1}
+FactoryTypeParserException.4=DBType {0} could not be resolved while registering typeMapping factoryType {1}
diff --git a/org.eclipse.emf.cdo.server/.classpath b/org.eclipse.emf.cdo.server/.classpath
new file mode 100644
index 0000000..64c5e31
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/org.eclipse.emf.cdo.server/.options b/org.eclipse.emf.cdo.server/.options
new file mode 100644
index 0000000..83038cb
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/.options
@@ -0,0 +1,11 @@
+# Debugging and tracing options
+
+org.eclipse.emf.cdo.server/debug = true
+org.eclipse.emf.cdo.server/debug.protocol = true
+org.eclipse.emf.cdo.server/debug.repository = true
+org.eclipse.emf.cdo.server/debug.session = true
+org.eclipse.emf.cdo.server/debug.transaction = true
+org.eclipse.emf.cdo.server/debug.revision = true
+org.eclipse.emf.cdo.server/debug.resource = true
+org.eclipse.emf.cdo.server/debug.store = true
+org.eclipse.emf.cdo.server/debug.types = true
diff --git a/org.eclipse.emf.cdo.server/.project b/org.eclipse.emf.cdo.server/.project
new file mode 100644
index 0000000..08924a8
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/.project
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.emf.cdo.server</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.api.tools.apiAnalysisBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.emf.cdo.releng.version.VersionBuilder</name>
+			<arguments>
+				<dictionary>
+					<key>release.path</key>
+					<value>/org.eclipse.emf.cdo.releng/release.xml</value>
+				</dictionary>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.pde.api.tools.apiAnalysisNature</nature>
+		<nature>org.eclipse.emf.cdo.releng.version.VersionNature</nature>
+	</natures>
+</projectDescription>
diff --git a/org.eclipse.emf.cdo.server/.settings/.api_filters b/org.eclipse.emf.cdo.server/.settings/.api_filters
new file mode 100644
index 0000000..833c776
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/.settings/.api_filters
@@ -0,0 +1,324 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>

+<component id="org.eclipse.emf.cdo.server" version="2">

+    <resource path="src/org/eclipse/emf/cdo/internal/server/DelegatingRepository.java" type="org.eclipse.emf.cdo.internal.server.DelegatingRepository">

+        <filter id="574660632">

+            <message_arguments>

+                <message_argument value="InternalRepository"/>

+                <message_argument value="CDOCommonRepository"/>

+                <message_argument value="DelegatingRepository"/>

+            </message_arguments>

+        </filter>

+    </resource>

+    <resource path="src/org/eclipse/emf/cdo/internal/server/LockManager.java" type="org.eclipse.emf.cdo.internal.server.LockManager$DurableView">

+        <filter id="574619656">

+            <message_arguments>

+                <message_argument value="Options"/>

+                <message_argument value="DurableView"/>

+            </message_arguments>

+        </filter>

+        <filter id="574660632">

+            <message_arguments>

+                <message_argument value="IView"/>

+                <message_argument value="CDOCommonView"/>

+                <message_argument value="DurableView"/>

+            </message_arguments>

+        </filter>

+    </resource>

+    <resource path="src/org/eclipse/emf/cdo/internal/server/QueryManager.java" type="org.eclipse.emf.cdo.internal.server.QueryManager$QueryContext">

+        <filter id="574660632">

+            <message_arguments>

+                <message_argument value="IQueryContext"/>

+                <message_argument value="CDOBranchPoint"/>

+                <message_argument value="QueryContext"/>

+            </message_arguments>

+        </filter>

+    </resource>

+    <resource path="src/org/eclipse/emf/cdo/internal/server/Repository.java" type="org.eclipse.emf.cdo.internal.server.Repository">

+        <filter id="574619656">

+            <message_arguments>

+                <message_argument value="CDOReplicationInfo"/>

+                <message_argument value="Repository"/>

+            </message_arguments>

+        </filter>

+        <filter id="574660632">

+            <message_arguments>

+                <message_argument value="InternalRepository"/>

+                <message_argument value="CDOCommonRepository"/>

+                <message_argument value="Repository"/>

+            </message_arguments>

+        </filter>

+    </resource>

+    <resource path="src/org/eclipse/emf/cdo/internal/server/ResourcesQueryHandler.java" type="org.eclipse.emf.cdo.internal.server.ResourcesQueryHandler$QueryContext">

+        <filter id="574660632">

+            <message_arguments>

+                <message_argument value="QueryResourcesContext"/>

+                <message_argument value="CDOBranchPoint"/>

+                <message_argument value="QueryContext"/>

+            </message_arguments>

+        </filter>

+    </resource>

+    <resource path="src/org/eclipse/emf/cdo/internal/server/ServerCDOView.java" type="org.eclipse.emf.cdo.internal.server.ServerCDOView">

+        <filter id="574619656">

+            <message_arguments>

+                <message_argument value="Options"/>

+                <message_argument value="ServerCDOView"/>

+            </message_arguments>

+        </filter>

+    </resource>

+    <resource path="src/org/eclipse/emf/cdo/internal/server/ServerCDOView.java" type="org.eclipse.emf.cdo.internal.server.ServerCDOView$ServerCDOSession">

+        <filter id="574619656">

+            <message_arguments>

+                <message_argument value="CDORepositoryInfo"/>

+                <message_argument value="ServerCDOSession"/>

+            </message_arguments>

+        </filter>

+        <filter id="574619656">

+            <message_arguments>

+                <message_argument value="InternalCDOSession"/>

+                <message_argument value="ServerCDOSession"/>

+            </message_arguments>

+        </filter>

+    </resource>

+    <resource path="src/org/eclipse/emf/cdo/internal/server/Session.java" type="org.eclipse.emf.cdo.internal.server.Session">

+        <filter id="574660632">

+            <message_arguments>

+                <message_argument value="InternalSession"/>

+                <message_argument value="CDOCommonSession"/>

+                <message_argument value="Session"/>

+            </message_arguments>

+        </filter>

+    </resource>

+    <resource path="src/org/eclipse/emf/cdo/internal/server/TransactionCommitContext.java" type="org.eclipse.emf.cdo.internal.server.TransactionCommitContext$DeltaLockWrapper">

+        <filter id="574619656">

+            <message_arguments>

+                <message_argument value="CDOIDAndBranch"/>

+                <message_argument value="DeltaLockWrapper"/>

+            </message_arguments>

+        </filter>

+    </resource>

+    <resource path="src/org/eclipse/emf/cdo/internal/server/TransactionCommitContext.java" type="org.eclipse.emf.cdo.internal.server.TransactionCommitContext$XRefContext">

+        <filter id="572522506">

+            <message_arguments>

+                <message_argument value="CDOIDReference"/>

+                <message_argument value="XRefContext"/>

+            </message_arguments>

+        </filter>

+        <filter id="574660632">

+            <message_arguments>

+                <message_argument value="QueryXRefsContext"/>

+                <message_argument value="CDOBranchPoint"/>

+                <message_argument value="XRefContext"/>

+            </message_arguments>

+        </filter>

+    </resource>

+    <resource path="src/org/eclipse/emf/cdo/internal/server/View.java" type="org.eclipse.emf.cdo.internal.server.View">

+        <filter id="574619656">

+            <message_arguments>

+                <message_argument value="Options"/>

+                <message_argument value="View"/>

+            </message_arguments>

+        </filter>

+        <filter id="574660632">

+            <message_arguments>

+                <message_argument value="InternalView"/>

+                <message_argument value="CDOCommonView"/>

+                <message_argument value="View"/>

+            </message_arguments>

+        </filter>

+    </resource>

+    <resource path="src/org/eclipse/emf/cdo/internal/server/XRefsQueryHandler.java" type="org.eclipse.emf.cdo.internal.server.XRefsQueryHandler$QueryContext">

+        <filter id="572522506">

+            <message_arguments>

+                <message_argument value="CDOIDReference"/>

+                <message_argument value="QueryContext"/>

+            </message_arguments>

+        </filter>

+        <filter id="574660632">

+            <message_arguments>

+                <message_argument value="QueryXRefsContext"/>

+                <message_argument value="CDOBranchPoint"/>

+                <message_argument value="QueryContext"/>

+            </message_arguments>

+        </filter>

+    </resource>

+    <resource path="src/org/eclipse/emf/cdo/internal/server/embedded/EmbeddedClientSessionConfiguration.java" type="org.eclipse.emf.cdo.internal.server.embedded.EmbeddedClientSessionConfiguration$RepositoryInfo">

+        <filter id="574619656">

+            <message_arguments>

+                <message_argument value="CDORepositoryInfo"/>

+                <message_argument value="RepositoryInfo"/>

+            </message_arguments>

+        </filter>

+    </resource>

+    <resource path="src/org/eclipse/emf/cdo/internal/server/embedded/EmbeddedClientSessionProtocol.java" type="org.eclipse.emf.cdo.internal.server.embedded.EmbeddedClientSessionProtocol">

+        <filter id="574619656">

+            <message_arguments>

+                <message_argument value="CDOSessionProtocol"/>

+                <message_argument value="EmbeddedClientSessionProtocol"/>

+            </message_arguments>

+        </filter>

+    </resource>

+    <resource path="src/org/eclipse/emf/cdo/internal/server/embedded/EmbeddedServerSessionProtocol.java" type="org.eclipse.emf.cdo.internal.server.embedded.EmbeddedServerSessionProtocol">

+        <filter id="574660632">

+            <message_arguments>

+                <message_argument value="ISessionProtocol"/>

+                <message_argument value="CDOProtocol"/>

+                <message_argument value="EmbeddedServerSessionProtocol"/>

+            </message_arguments>

+        </filter>

+    </resource>

+    <resource path="src/org/eclipse/emf/cdo/internal/server/mem/MEMStore.java" type="org.eclipse.emf.cdo.internal.server.mem.MEMStore">

+        <filter id="574660632">

+            <message_arguments>

+                <message_argument value="DurableLocking"/>

+                <message_argument value="IDurableLockingManager"/>

+                <message_argument value="MEMStore"/>

+            </message_arguments>

+        </filter>

+    </resource>

+    <resource path="src/org/eclipse/emf/cdo/internal/server/mem/MEMStoreAccessor.java" type="org.eclipse.emf.cdo.internal.server.mem.MEMStoreAccessor">

+        <filter id="574660632">

+            <message_arguments>

+                <message_argument value="DurableLocking"/>

+                <message_argument value="IDurableLockingManager"/>

+                <message_argument value="MEMStoreAccessor"/>

+            </message_arguments>

+        </filter>

+    </resource>

+    <resource path="src/org/eclipse/emf/cdo/internal/server/syncing/OfflineClone.java" type="org.eclipse.emf.cdo.internal.server.syncing.OfflineClone$CommitContextData">

+        <filter id="574619656">

+            <message_arguments>

+                <message_argument value="CDOCommitData"/>

+                <message_argument value="CommitContextData"/>

+            </message_arguments>

+        </filter>

+    </resource>

+    <resource path="src/org/eclipse/emf/cdo/server/IQueryContext.java" type="org.eclipse.emf.cdo.server.IQueryContext">

+        <filter id="571473929">

+            <message_arguments>

+                <message_argument value="CDOBranchPoint"/>

+                <message_argument value="IQueryContext"/>

+            </message_arguments>

+        </filter>

+    </resource>

+    <resource path="src/org/eclipse/emf/cdo/server/IRepository.java" type="org.eclipse.emf.cdo.server.IRepository">

+        <filter id="574619656">

+            <message_arguments>

+                <message_argument value="CDOCommonRepository"/>

+                <message_argument value="IRepository"/>

+            </message_arguments>

+        </filter>

+    </resource>

+    <resource path="src/org/eclipse/emf/cdo/server/ISession.java" type="org.eclipse.emf.cdo.server.ISession">

+        <filter id="574619656">

+            <message_arguments>

+                <message_argument value="CDOCommonSession"/>

+                <message_argument value="ISession"/>

+            </message_arguments>

+        </filter>

+    </resource>

+    <resource path="src/org/eclipse/emf/cdo/server/IStoreAccessor.java" type="org.eclipse.emf.cdo.server.IStoreAccessor$DurableLocking">

+        <filter id="571473929">

+            <message_arguments>

+                <message_argument value="IDurableLockingManager"/>

+                <message_argument value="DurableLocking"/>

+            </message_arguments>

+        </filter>

+    </resource>

+    <resource path="src/org/eclipse/emf/cdo/server/IStoreAccessor.java" type="org.eclipse.emf.cdo.server.IStoreAccessor$QueryResourcesContext">

+        <filter id="571473929">

+            <message_arguments>

+                <message_argument value="CDOBranchPoint"/>

+                <message_argument value="QueryResourcesContext"/>

+            </message_arguments>

+        </filter>

+    </resource>

+    <resource path="src/org/eclipse/emf/cdo/server/IStoreAccessor.java" type="org.eclipse.emf.cdo.server.IStoreAccessor$QueryXRefsContext">

+        <filter id="571473929">

+            <message_arguments>

+                <message_argument value="CDOBranchPoint"/>

+                <message_argument value="QueryXRefsContext"/>

+            </message_arguments>

+        </filter>

+    </resource>

+    <resource path="src/org/eclipse/emf/cdo/server/ITransaction.java" type="org.eclipse.emf.cdo.server.ITransaction">

+        <filter id="571473929">

+            <message_arguments>

+                <message_argument value="CDOCommonTransaction"/>

+                <message_argument value="ITransaction"/>

+            </message_arguments>

+        </filter>

+    </resource>

+    <resource path="src/org/eclipse/emf/cdo/server/IView.java" type="org.eclipse.emf.cdo.server.IView">

+        <filter id="571473929">

+            <message_arguments>

+                <message_argument value="CDOCommonView"/>

+                <message_argument value="IView"/>

+            </message_arguments>

+        </filter>

+    </resource>

+    <resource path="src/org/eclipse/emf/cdo/server/embedded/CDOSession.java" type="org.eclipse.emf.cdo.server.embedded.CDOSession">

+        <filter id="571473929">

+            <message_arguments>

+                <message_argument value="CDOSession"/>

+                <message_argument value="CDOSession"/>

+            </message_arguments>

+        </filter>

+    </resource>

+    <resource path="src/org/eclipse/emf/cdo/server/embedded/CDOSessionConfiguration.java" type="org.eclipse.emf.cdo.server.embedded.CDOSessionConfiguration">

+        <filter id="571473929">

+            <message_arguments>

+                <message_argument value="CDOSessionConfiguration"/>

+                <message_argument value="CDOSessionConfiguration"/>

+            </message_arguments>

+        </filter>

+    </resource>

+    <resource path="src/org/eclipse/emf/cdo/spi/server/DurableLockArea.java" type="org.eclipse.emf.cdo.spi.server.DurableLockArea">

+        <filter id="574619656">

+            <message_arguments>

+                <message_argument value="LockArea"/>

+                <message_argument value="DurableLockArea"/>

+            </message_arguments>

+        </filter>

+    </resource>

+    <resource path="src/org/eclipse/emf/cdo/spi/server/ISessionProtocol.java" type="org.eclipse.emf.cdo.spi.server.ISessionProtocol">

+        <filter id="571473929">

+            <message_arguments>

+                <message_argument value="CDOProtocol"/>

+                <message_argument value="ISessionProtocol"/>

+            </message_arguments>

+        </filter>

+    </resource>

+    <resource path="src/org/eclipse/emf/cdo/spi/server/InternalLockManager.java" type="org.eclipse.emf.cdo.spi.server.InternalLockManager">

+        <filter id="574619656">

+            <message_arguments>

+                <message_argument value="IDurableLockingManager"/>

+                <message_argument value="InternalLockManager"/>

+            </message_arguments>

+        </filter>

+    </resource>

+    <resource path="src/org/eclipse/emf/cdo/spi/server/InternalSession.java" type="org.eclipse.emf.cdo.spi.server.InternalSession">

+        <filter id="571473929">

+            <message_arguments>

+                <message_argument value="Options"/>

+                <message_argument value="InternalSession"/>

+            </message_arguments>

+        </filter>

+    </resource>

+    <resource path="src/org/eclipse/emf/cdo/spi/server/InternalSynchronizableRepository.java" type="org.eclipse.emf.cdo.spi.server.InternalSynchronizableRepository">

+        <filter id="571473929">

+            <message_arguments>

+                <message_argument value="CDOReplicationContext"/>

+                <message_argument value="InternalSynchronizableRepository"/>

+            </message_arguments>

+        </filter>

+    </resource>

+    <resource path="src/org/eclipse/emf/cdo/spi/server/Store.java" type="org.eclipse.emf.cdo.spi.server.Store">

+        <filter id="574660632">

+            <message_arguments>

+                <message_argument value="ExactMatch"/>

+                <message_argument value="CDOBranchPoint"/>

+                <message_argument value="Store"/>

+            </message_arguments>

+        </filter>

+    </resource>

+</component>

diff --git a/org.eclipse.emf.cdo.server/.settings/org.eclipse.core.resources.prefs b/org.eclipse.emf.cdo.server/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..9d1e69b
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Mon Jul 04 13:03:48 CEST 2011

+eclipse.preferences.version=1

+encoding//model/org.eclipse.emf.cdo.defs.ecorediag=UTF-8

diff --git a/org.eclipse.emf.cdo.server/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.emf.cdo.server/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..611d1a9
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,373 @@
+#Fri Sep 02 05:40:11 CEST 2011

+eclipse.preferences.version=1

+org.eclipse.jdt.core.builder.cleanOutputFolder=clean

+org.eclipse.jdt.core.builder.duplicateResourceTask=warning

+org.eclipse.jdt.core.builder.invalidClasspath=abort

+org.eclipse.jdt.core.builder.recreateModifiedClassFileInOutputFolder=ignore

+org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch,*.ucls,doc-files/,package.html,package-info.java

+org.eclipse.jdt.core.circularClasspath=error

+org.eclipse.jdt.core.classpath.exclusionPatterns=enabled

+org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled

+org.eclipse.jdt.core.codeComplete.argumentPrefixes=

+org.eclipse.jdt.core.codeComplete.argumentSuffixes=

+org.eclipse.jdt.core.codeComplete.fieldPrefixes=

+org.eclipse.jdt.core.codeComplete.fieldSuffixes=

+org.eclipse.jdt.core.codeComplete.localPrefixes=

+org.eclipse.jdt.core.codeComplete.localSuffixes=

+org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=

+org.eclipse.jdt.core.codeComplete.staticFieldSuffixes=

+org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes=

+org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes=

+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled

+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5

+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve

+org.eclipse.jdt.core.compiler.compliance=1.5

+org.eclipse.jdt.core.compiler.debug.lineNumber=generate

+org.eclipse.jdt.core.compiler.debug.localVariable=generate

+org.eclipse.jdt.core.compiler.debug.sourceFile=generate

+org.eclipse.jdt.core.compiler.doc.comment.support=enabled

+org.eclipse.jdt.core.compiler.maxProblemPerUnit=100

+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning

+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error

+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore

+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning

+org.eclipse.jdt.core.compiler.problem.deadCode=warning

+org.eclipse.jdt.core.compiler.problem.deprecation=warning

+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled

+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=enabled

+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning

+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning

+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error

+org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning

+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled

+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore

+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning

+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning

+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error

+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning

+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled

+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning

+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore

+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore

+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning

+org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled

+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=disabled

+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=disabled

+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=public

+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore

+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning

+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning

+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning

+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore

+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled

+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public

+org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=return_tag

+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore

+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled

+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public

+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning

+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled

+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning

+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=warning

+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning

+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning

+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore

+org.eclipse.jdt.core.compiler.problem.nullReference=warning

+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning

+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore

+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning

+org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore

+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning

+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning

+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning

+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled

+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning

+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled

+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled

+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore

+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning

+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning

+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore

+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning

+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning

+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning

+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore

+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore

+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled

+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled

+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled

+org.eclipse.jdt.core.compiler.problem.unusedImport=warning

+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning

+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning

+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore

+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore

+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled

+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled

+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled

+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning

+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning

+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning

+org.eclipse.jdt.core.compiler.source=1.5

+org.eclipse.jdt.core.compiler.taskCaseSensitive=enabled

+org.eclipse.jdt.core.compiler.taskPriorities=NORMAL,HIGH,HIGH,LOW,LOW,LOW,LOW,LOW

+org.eclipse.jdt.core.compiler.taskTags=TODO,FIXME,XXX,PERF,MEM,POLISH,@generated NOT,@ADDED

+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false

+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16

+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16

+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16

+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16

+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16

+org.eclipse.jdt.core.formatter.alignment_for_assignment=0

+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16

+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16

+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80

+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0

+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16

+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16

+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16

+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16

+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16

+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16

+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16

+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16

+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16

+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16

+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1

+org.eclipse.jdt.core.formatter.blank_lines_after_package=1

+org.eclipse.jdt.core.formatter.blank_lines_before_field=1

+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0

+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1

+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1

+org.eclipse.jdt.core.formatter.blank_lines_before_method=1

+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1

+org.eclipse.jdt.core.formatter.blank_lines_before_package=0

+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1

+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1

+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=next_line

+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=next_line

+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line

+org.eclipse.jdt.core.formatter.brace_position_for_block=next_line

+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=next_line

+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=next_line

+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=next_line

+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=next_line

+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=next_line

+org.eclipse.jdt.core.formatter.brace_position_for_switch=next_line

+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=next_line

+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=true

+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=true

+org.eclipse.jdt.core.formatter.comment.format_block_comments=true

+org.eclipse.jdt.core.formatter.comment.format_header=false

+org.eclipse.jdt.core.formatter.comment.format_html=true

+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true

+org.eclipse.jdt.core.formatter.comment.format_line_comments=true

+org.eclipse.jdt.core.formatter.comment.format_source_code=true

+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true

+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true

+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert

+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert

+org.eclipse.jdt.core.formatter.comment.line_length=120

+org.eclipse.jdt.core.formatter.compact_else_if=true

+org.eclipse.jdt.core.formatter.continuation_indentation=2

+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2

+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false

+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true

+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true

+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true

+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true

+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true

+org.eclipse.jdt.core.formatter.indent_empty_lines=false

+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true

+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true

+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true

+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false

+org.eclipse.jdt.core.formatter.indentation.size=2

+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert

+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert

+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert

+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert

+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=insert

+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert

+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert

+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=insert

+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert

+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert

+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert

+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert

+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert

+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert

+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert

+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert

+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert

+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert

+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert

+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert

+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert

+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert

+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert

+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert

+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert

+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert

+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert

+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert

+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert

+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert

+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert

+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert

+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert

+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert

+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert

+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert

+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert

+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert

+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert

+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert

+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert

+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert

+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert

+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert

+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert

+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert

+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert

+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert

+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert

+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert

+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert

+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert

+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert

+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert

+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert

+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert

+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert

+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert

+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert

+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert

+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert

+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert

+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert

+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert

+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert

+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert

+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert

+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert

+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert

+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert

+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert

+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert

+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert

+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert

+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert

+org.eclipse.jdt.core.formatter.join_lines_in_comments=true

+org.eclipse.jdt.core.formatter.join_wrapped_lines=true

+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false

+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false

+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false

+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false

+org.eclipse.jdt.core.formatter.lineSplit=120

+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false

+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false

+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0

+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1

+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true

+org.eclipse.jdt.core.formatter.tabulation.char=space

+org.eclipse.jdt.core.formatter.tabulation.size=2

+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false

+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true

+org.eclipse.jdt.core.incompatibleJDKLevel=ignore

+org.eclipse.jdt.core.incompleteClasspath=error

diff --git a/org.eclipse.emf.cdo.server/.settings/org.eclipse.jdt.launching.prefs b/org.eclipse.emf.cdo.server/.settings/org.eclipse.jdt.launching.prefs
new file mode 100644
index 0000000..4658ec1
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/.settings/org.eclipse.jdt.launching.prefs
@@ -0,0 +1,3 @@
+#Fri Sep 02 05:38:34 CEST 2011

+eclipse.preferences.version=1

+org.eclipse.jdt.launching.PREF_STRICTLY_COMPATIBLE_JRE_NOT_AVAILABLE=ignore

diff --git a/org.eclipse.emf.cdo.server/.settings/org.eclipse.jdt.ui.prefs b/org.eclipse.emf.cdo.server/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..4277817
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,120 @@
+#Thu Feb 04 09:44:24 CET 2010
+cleanup.add_default_serial_version_id=true
+cleanup.add_generated_serial_version_id=false
+cleanup.add_missing_annotations=true
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_methods=false
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=true
+cleanup.add_missing_override_annotations_interface_methods=true
+cleanup.add_serial_version_id=true
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=false
+cleanup.always_use_this_for_non_static_field_access=false
+cleanup.always_use_this_for_non_static_method_access=false
+cleanup.convert_to_enhanced_for_loop=false
+cleanup.correct_indentation=true
+cleanup.format_source_code=true
+cleanup.format_source_code_changes_only=false
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=false
+cleanup.make_private_fields_final=true
+cleanup.make_type_abstract_if_missing_method=false
+cleanup.make_variable_declarations_final=false
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=true
+cleanup.organize_imports=true
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+cleanup.qualify_static_member_accesses_with_declaring_class=false
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.remove_private_constructors=true
+cleanup.remove_trailing_whitespaces=true
+cleanup.remove_trailing_whitespaces_all=true
+cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.sort_members=false
+cleanup.sort_members_all=false
+cleanup.use_blocks=true
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_parentheses_in_expressions=true
+cleanup.use_this_for_non_static_field_access=true
+cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+cleanup.use_this_for_non_static_method_access=true
+cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+cleanup_profile=_EMFT
+cleanup_settings_version=2
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_EMFT
+formatter_settings_version=11
+org.eclipse.jdt.ui.exception.name=ex
+org.eclipse.jdt.ui.gettersetter.use.is=true
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=org.eclipse.emf.cdo;org.eclipse.emf.internal.cdo;org.eclipse.net4j;org.eclipse.internal.net4j;org.eclipse.emf;org.eclipse;com;org;javax;java;
+org.eclipse.jdt.ui.javadoc=true
+org.eclipse.jdt.ui.keywordthis=false
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.overrideannotation=true
+org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates><template autoinsert\="false" context\="gettercomment_context" deleted\="false" description\="Comment for getter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.gettercomment" name\="gettercomment"/><template autoinsert\="false" context\="settercomment_context" deleted\="false" description\="Comment for setter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.settercomment" name\="settercomment"/><template autoinsert\="false" context\="constructorcomment_context" deleted\="false" description\="Comment for created constructors" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorcomment" name\="constructorcomment"/><template autoinsert\="false" context\="filecomment_context" deleted\="false" description\="Comment for created Java files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.filecomment" name\="filecomment">/**\r\n * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.\r\n * All rights reserved. This program and the accompanying materials\r\n * are made available under the terms of the Eclipse Public License v1.0\r\n * which accompanies this distribution, and is available at\r\n * http\://www.eclipse.org/legal/epl-v10.html\r\n * \r\n * Contributors\:\r\n *    Eike Stepper - initial API and implementation\r\n */</template><template autoinsert\="false" context\="typecomment_context" deleted\="false" description\="Comment for created types" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.typecomment" name\="typecomment">/**\r\n * @author Eike Stepper\r\n */</template><template autoinsert\="false" context\="fieldcomment_context" deleted\="false" description\="Comment for fields" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment"/><template autoinsert\="false" context\="methodcomment_context" deleted\="false" description\="Comment for non-overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodcomment" name\="methodcomment"/><template autoinsert\="false" context\="overridecomment_context" deleted\="false" description\="Comment for overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.overridecomment" name\="overridecomment"/><template autoinsert\="false" context\="delegatecomment_context" deleted\="false" description\="Comment for delegate methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.delegatecomment" name\="delegatecomment"/><template autoinsert\="true" context\="newtype_context" deleted\="false" description\="Newly created files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.newtype" name\="newtype">${filecomment}\r\n${package_declaration}\r\n\r\n${typecomment}\r\n${type_declaration}</template><template autoinsert\="true" context\="classbody_context" deleted\="false" description\="Code in new class type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.classbody" name\="classbody">\r\n</template><template autoinsert\="true" context\="interfacebody_context" deleted\="false" description\="Code in new interface type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.interfacebody" name\="interfacebody">\r\n</template><template autoinsert\="true" context\="enumbody_context" deleted\="false" description\="Code in new enum type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.enumbody" name\="enumbody">\r\n</template><template autoinsert\="true" context\="annotationbody_context" deleted\="false" description\="Code in new annotation type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.annotationbody" name\="annotationbody">\r\n</template><template autoinsert\="false" context\="catchblock_context" deleted\="false" description\="Code in new catch blocks" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.catchblock" name\="catchblock">${exception_var}.printStackTrace();</template><template autoinsert\="false" context\="methodbody_context" deleted\="false" description\="Code in created method stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodbody" name\="methodbody">${body_statement}</template><template autoinsert\="false" context\="constructorbody_context" deleted\="false" description\="Code in created constructor stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorbody" name\="constructorbody">${body_statement}</template><template autoinsert\="true" context\="getterbody_context" deleted\="false" description\="Code in created getters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.getterbody" name\="getterbody">return ${field};</template><template autoinsert\="true" context\="setterbody_context" deleted\="false" description\="Code in created setters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.setterbody" name\="setterbody">${field} \= ${param};</template></templates>
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=true
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_missing_override_annotations_interface_methods=false
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=false
+sp_cleanup.always_use_this_for_non_static_method_access=false
+sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.correct_indentation=true
+sp_cleanup.format_source_code=true
+sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.make_local_variable_final=false
+sp_cleanup.make_parameters_final=false
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.organize_imports=true
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_trailing_whitespaces=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_casts=true
+sp_cleanup.remove_unnecessary_nls_tags=true
+sp_cleanup.remove_unused_imports=true
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.use_blocks=true
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_parentheses_in_expressions=true
+sp_cleanup.use_this_for_non_static_field_access=true
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+sp_cleanup.use_this_for_non_static_method_access=true
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
diff --git a/org.eclipse.emf.cdo.server/.settings/org.eclipse.ltk.core.refactoring.prefs b/org.eclipse.emf.cdo.server/.settings/org.eclipse.ltk.core.refactoring.prefs
new file mode 100644
index 0000000..864e30f
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/.settings/org.eclipse.ltk.core.refactoring.prefs
@@ -0,0 +1,3 @@
+#Thu Feb 04 09:44:24 CET 2010
+eclipse.preferences.version=1
+org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false
diff --git a/org.eclipse.emf.cdo.server/.settings/org.eclipse.mylyn.tasks.ui.prefs b/org.eclipse.emf.cdo.server/.settings/org.eclipse.mylyn.tasks.ui.prefs
new file mode 100644
index 0000000..b050639
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/.settings/org.eclipse.mylyn.tasks.ui.prefs
@@ -0,0 +1,4 @@
+#Thu Feb 04 09:44:24 CET 2010
+eclipse.preferences.version=1
+project.repository.kind=bugzilla
+project.repository.url=https\://bugs.eclipse.org/bugs
diff --git a/org.eclipse.emf.cdo.server/.settings/org.eclipse.mylyn.team.ui.prefs b/org.eclipse.emf.cdo.server/.settings/org.eclipse.mylyn.team.ui.prefs
new file mode 100644
index 0000000..2f50f36
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/.settings/org.eclipse.mylyn.team.ui.prefs
@@ -0,0 +1,3 @@
+#Thu Feb 04 09:44:24 CET 2010
+commit.comment.template=[${task.id}] ${task.description} \r\n${task.url}
+eclipse.preferences.version=1
diff --git a/org.eclipse.emf.cdo.server/.settings/org.eclipse.pde.api.tools.prefs b/org.eclipse.emf.cdo.server/.settings/org.eclipse.pde.api.tools.prefs
new file mode 100644
index 0000000..b0e5218
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/.settings/org.eclipse.pde.api.tools.prefs
@@ -0,0 +1,94 @@
+#Mon May 16 19:22:50 CEST 2011

+ANNOTATION_ELEMENT_TYPE_ADDED_METHOD_WITHOUT_DEFAULT_VALUE=Error

+ANNOTATION_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error

+ANNOTATION_ELEMENT_TYPE_REMOVED_FIELD=Error

+ANNOTATION_ELEMENT_TYPE_REMOVED_METHOD=Error

+ANNOTATION_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error

+API_COMPONENT_ELEMENT_TYPE_REMOVED_API_TYPE=Error

+API_COMPONENT_ELEMENT_TYPE_REMOVED_REEXPORTED_API_TYPE=Error

+API_COMPONENT_ELEMENT_TYPE_REMOVED_REEXPORTED_TYPE=Error

+API_COMPONENT_ELEMENT_TYPE_REMOVED_TYPE=Error

+CLASS_ELEMENT_TYPE_ADDED_METHOD=Error

+CLASS_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error

+CLASS_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error

+CLASS_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error

+CLASS_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error

+CLASS_ELEMENT_TYPE_CHANGED_NON_ABSTRACT_TO_ABSTRACT=Error

+CLASS_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error

+CLASS_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error

+CLASS_ELEMENT_TYPE_REMOVED_CONSTRUCTOR=Error

+CLASS_ELEMENT_TYPE_REMOVED_FIELD=Error

+CLASS_ELEMENT_TYPE_REMOVED_METHOD=Error

+CLASS_ELEMENT_TYPE_REMOVED_SUPERCLASS=Error

+CLASS_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error

+CLASS_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error

+CONSTRUCTOR_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error

+CONSTRUCTOR_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error

+CONSTRUCTOR_ELEMENT_TYPE_CHANGED_VARARGS_TO_ARRAY=Error

+CONSTRUCTOR_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error

+ENUM_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error

+ENUM_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error

+ENUM_ELEMENT_TYPE_REMOVED_ENUM_CONSTANT=Error

+ENUM_ELEMENT_TYPE_REMOVED_FIELD=Error

+ENUM_ELEMENT_TYPE_REMOVED_METHOD=Error

+ENUM_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error

+FIELD_ELEMENT_TYPE_ADDED_VALUE=Error

+FIELD_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error

+FIELD_ELEMENT_TYPE_CHANGED_FINAL_TO_NON_FINAL_STATIC_CONSTANT=Error

+FIELD_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error

+FIELD_ELEMENT_TYPE_CHANGED_NON_STATIC_TO_STATIC=Error

+FIELD_ELEMENT_TYPE_CHANGED_STATIC_TO_NON_STATIC=Error

+FIELD_ELEMENT_TYPE_CHANGED_TYPE=Error

+FIELD_ELEMENT_TYPE_CHANGED_VALUE=Error

+FIELD_ELEMENT_TYPE_REMOVED_TYPE_ARGUMENT=Error

+FIELD_ELEMENT_TYPE_REMOVED_VALUE=Error

+ILLEGAL_EXTEND=Warning

+ILLEGAL_IMPLEMENT=Warning

+ILLEGAL_INSTANTIATE=Warning

+ILLEGAL_OVERRIDE=Warning

+ILLEGAL_REFERENCE=Warning

+INTERFACE_ELEMENT_TYPE_ADDED_FIELD=Error

+INTERFACE_ELEMENT_TYPE_ADDED_METHOD=Error

+INTERFACE_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error

+INTERFACE_ELEMENT_TYPE_ADDED_SUPER_INTERFACE_WITH_METHODS=Error

+INTERFACE_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error

+INTERFACE_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error

+INTERFACE_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error

+INTERFACE_ELEMENT_TYPE_REMOVED_FIELD=Error

+INTERFACE_ELEMENT_TYPE_REMOVED_METHOD=Error

+INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error

+INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error

+INVALID_JAVADOC_TAG=Ignore

+INVALID_REFERENCE_IN_SYSTEM_LIBRARIES=Ignore

+LEAK_EXTEND=Warning

+LEAK_FIELD_DECL=Warning

+LEAK_IMPLEMENT=Warning

+LEAK_METHOD_PARAM=Warning

+LEAK_METHOD_RETURN_TYPE=Warning

+METHOD_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error

+METHOD_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error

+METHOD_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error

+METHOD_ELEMENT_TYPE_CHANGED_NON_ABSTRACT_TO_ABSTRACT=Error

+METHOD_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error

+METHOD_ELEMENT_TYPE_CHANGED_NON_STATIC_TO_STATIC=Error

+METHOD_ELEMENT_TYPE_CHANGED_STATIC_TO_NON_STATIC=Error

+METHOD_ELEMENT_TYPE_CHANGED_VARARGS_TO_ARRAY=Error

+METHOD_ELEMENT_TYPE_REMOVED_ANNOTATION_DEFAULT_VALUE=Error

+METHOD_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error

+TYPE_PARAMETER_ELEMENT_TYPE_ADDED_CLASS_BOUND=Error

+TYPE_PARAMETER_ELEMENT_TYPE_ADDED_INTERFACE_BOUND=Error

+TYPE_PARAMETER_ELEMENT_TYPE_CHANGED_CLASS_BOUND=Error

+TYPE_PARAMETER_ELEMENT_TYPE_CHANGED_INTERFACE_BOUND=Error

+TYPE_PARAMETER_ELEMENT_TYPE_REMOVED_CLASS_BOUND=Error

+TYPE_PARAMETER_ELEMENT_TYPE_REMOVED_INTERFACE_BOUND=Error

+UNUSED_PROBLEM_FILTERS=Ignore

+automatically_removed_unused_problem_filters=Disabled

+eclipse.preferences.version=1

+incompatible_api_component_version=Error

+incompatible_api_component_version_include_major_without_breaking_change=Disabled

+incompatible_api_component_version_include_minor_without_api_change=Disabled

+invalid_since_tag_version=Error

+malformed_since_tag=Error

+missing_since_tag=Error

+report_api_breakage_when_major_version_incremented=Disabled

+report_resolution_errors_api_component=Warning

diff --git a/org.eclipse.emf.cdo.server/.settings/org.eclipse.pde.prefs b/org.eclipse.emf.cdo.server/.settings/org.eclipse.pde.prefs
new file mode 100644
index 0000000..c6b96bb
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/.settings/org.eclipse.pde.prefs
@@ -0,0 +1,31 @@
+#Thu Feb 04 09:44:24 CET 2010
+compilers.f.unresolved-features=1
+compilers.f.unresolved-plugins=1
+compilers.incompatible-environment=1
+compilers.p.build=1
+compilers.p.build.bin.includes=1
+compilers.p.build.java.compliance=1
+compilers.p.build.missing.output=2
+compilers.p.build.output.library=1
+compilers.p.build.source.library=1
+compilers.p.build.src.includes=1
+compilers.p.deprecated=1
+compilers.p.discouraged-class=1
+compilers.p.internal=1
+compilers.p.missing-packages=1
+compilers.p.missing-version-export-package=1
+compilers.p.missing-version-import-package=1
+compilers.p.missing-version-require-bundle=1
+compilers.p.no-required-att=0
+compilers.p.not-externalized-att=2
+compilers.p.unknown-attribute=1
+compilers.p.unknown-class=1
+compilers.p.unknown-element=1
+compilers.p.unknown-identifier=1
+compilers.p.unknown-resource=1
+compilers.p.unresolved-ex-points=0
+compilers.p.unresolved-import=0
+compilers.s.create-docs=false
+compilers.s.doc-folder=doc
+compilers.s.open-tags=1
+eclipse.preferences.version=1
diff --git a/org.eclipse.emf.cdo.server/CDOServer.launch b/org.eclipse.emf.cdo.server/CDOServer.launch
new file mode 100644
index 0000000..bd3d8e9
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/CDOServer.launch
@@ -0,0 +1,368 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>

+<launchConfiguration type="org.eclipse.pde.ui.RuntimeWorkbench">

+<booleanAttribute key="append.args" value="true"/>

+<stringAttribute key="application" value="org.eclipse.emf.cdo.server.app"/>

+<booleanAttribute key="askclear" value="true"/>

+<booleanAttribute key="automaticAdd" value="false"/>

+<booleanAttribute key="automaticValidate" value="false"/>

+<stringAttribute key="bootstrap" value=""/>

+<stringAttribute key="checked" value="org.eclipse.emf.cdo.server,org.eclipse.emf.cdo.server.db,org.eclipse.net4j,org.eclipse.net4j.db,org.eclipse.net4j.db.derby,org.eclipse.net4j.http.common,org.eclipse.net4j.http.server,org.eclipse.net4j.tcp,org.eclipse.net4j.util"/>

+<booleanAttribute key="clearConfig" value="true"/>

+<booleanAttribute key="clearws" value="false"/>

+<booleanAttribute key="clearwslog" value="false"/>

+<stringAttribute key="configLocation" value="${workspace_loc}/.metadata/.plugins/org.eclipse.pde.core/CDOServer"/>

+<booleanAttribute key="default" value="false"/>

+<booleanAttribute key="includeOptional" value="true"/>

+<stringAttribute key="location" value="${workspace_loc}/../cdo.server"/>

+<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/>

+<mapAttribute key="org.eclipse.debug.core.preferred_launchers">

+<mapEntry key="[run]" value="org.eclipse.pde.ui.RuntimeWorkbench"/>

+</mapAttribute>

+<listAttribute key="org.eclipse.debug.ui.favoriteGroups">

+<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>

+<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>

+</listAttribute>

+<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>

+<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl}&#13;&#10;-debug&#13;&#10;-console"/>

+<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.pde.ui.workbenchClasspathProvider"/>

+<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xms40m&#13;&#10;-Xmx1024m&#13;&#10;-Ddebug=true&#13;&#10;-Dnet4j.config=&quot;${project_loc:/org.eclipse.emf.cdo.server.product}/config&quot;&#13;&#10;-Dorg.eclipse.emf.cdo.server.browser.port=7777&#13;&#10;-Dorg.osgi.service.http.port=8080"/>

+<stringAttribute key="pde.version" value="3.3"/>

+<stringAttribute key="product" value="org.eclipse.platform.ide"/>

+<stringAttribute key="selectedPlugin" value="org.eclipse.emf.cdo"/>

+<stringAttribute key="selected_target_plugins" value="com.mysql.jdbc@default:default,javax.servlet@default:default,org.apache.derby@default:default,org.eclipse.ant.core@default:default,org.eclipse.core.contenttype@default:default,org.eclipse.core.expressions@default:default,org.eclipse.core.filesystem.win32.x86_64@default:false,org.eclipse.core.filesystem@default:default,org.eclipse.core.jobs@default:default,org.eclipse.core.resources@default:default,org.eclipse.core.runtime.compatibility.auth@default:default,org.eclipse.core.runtime.compatibility.registry@default:false,org.eclipse.core.runtime@default:true,org.eclipse.core.variables@default:default,org.eclipse.emf.common@default:default,org.eclipse.emf.ecore.change@default:default,org.eclipse.emf.ecore.xmi@default:default,org.eclipse.emf.ecore@default:default,org.eclipse.equinox.app@default:default,org.eclipse.equinox.common@2:true,org.eclipse.equinox.preferences@default:default,org.eclipse.equinox.registry@default:default,org.eclipse.osgi.services@default:default,org.eclipse.osgi@-1:true,org.eclipse.team.core@default:default,org.h2@default:default,org.hsqldb@default:default,org.postgresql.jdbc3@default:default"/>

+<stringAttribute key="selected_workspace_plugins" value="com.mongodb@default:default,org.eclipse.emf.cdo.common@default:default,org.eclipse.emf.cdo.examples.company@default:default,org.eclipse.emf.cdo.server.db@default:default,org.eclipse.emf.cdo.server.mongodb@default:default,org.eclipse.emf.cdo.server.net4j@default:default,org.eclipse.emf.cdo.server@default:default,org.eclipse.emf.cdo@default:default,org.eclipse.net4j.db.derby@default:default,org.eclipse.net4j.db.h2@default:default,org.eclipse.net4j.db.hsqldb@default:default,org.eclipse.net4j.db.mysql@default:default,org.eclipse.net4j.db.postgresql@default:default,org.eclipse.net4j.db@default:default,org.eclipse.net4j.tcp@default:default,org.eclipse.net4j.util@default:default,org.eclipse.net4j@default:default"/>

+<booleanAttribute key="show_selected_only" value="false"/>

+<stringAttribute key="templateConfig" value="${target_home}\configuration\config.ini"/>

+<booleanAttribute key="tracing" value="true"/>

+<mapAttribute key="tracingOptions">

+<mapEntry key="org.eclipse.core.contenttype/debug" value="false"/>

+<mapEntry key="org.eclipse.core.expressions/tracePropertyResolving" value="false"/>

+<mapEntry key="org.eclipse.core.jobs/jobs" value="false"/>

+<mapEntry key="org.eclipse.core.jobs/jobs/beginend" value="false"/>

+<mapEntry key="org.eclipse.core.jobs/jobs/errorondeadlock" value="false"/>

+<mapEntry key="org.eclipse.core.jobs/jobs/locks" value="false"/>

+<mapEntry key="org.eclipse.core.jobs/jobs/shutdown" value="false"/>

+<mapEntry key="org.eclipse.core.jobs/jobs/timing" value="false"/>

+<mapEntry key="org.eclipse.core.resources/build/delta" value="false"/>

+<mapEntry key="org.eclipse.core.resources/build/failure" value="false"/>

+<mapEntry key="org.eclipse.core.resources/build/interrupt" value="false"/>

+<mapEntry key="org.eclipse.core.resources/build/invoking" value="false"/>

+<mapEntry key="org.eclipse.core.resources/build/needbuild" value="false"/>

+<mapEntry key="org.eclipse.core.resources/build/needbuildstack" value="false"/>

+<mapEntry key="org.eclipse.core.resources/build/stacktrace" value="false"/>

+<mapEntry key="org.eclipse.core.resources/contenttype" value="false"/>

+<mapEntry key="org.eclipse.core.resources/contenttype/cache" value="false"/>

+<mapEntry key="org.eclipse.core.resources/debug" value="false"/>

+<mapEntry key="org.eclipse.core.resources/history" value="false"/>

+<mapEntry key="org.eclipse.core.resources/natures" value="false"/>

+<mapEntry key="org.eclipse.core.resources/perf/builders" value="10000"/>

+<mapEntry key="org.eclipse.core.resources/perf/listeners" value="500"/>

+<mapEntry key="org.eclipse.core.resources/perf/save.participants" value="500"/>

+<mapEntry key="org.eclipse.core.resources/perf/snapshot" value="1000"/>

+<mapEntry key="org.eclipse.core.resources/preferences" value="false"/>

+<mapEntry key="org.eclipse.core.resources/refresh" value="false"/>

+<mapEntry key="org.eclipse.core.resources/restore" value="false"/>

+<mapEntry key="org.eclipse.core.resources/restore/markers" value="false"/>

+<mapEntry key="org.eclipse.core.resources/restore/mastertable" value="false"/>

+<mapEntry key="org.eclipse.core.resources/restore/metainfo" value="false"/>

+<mapEntry key="org.eclipse.core.resources/restore/snapshots" value="false"/>

+<mapEntry key="org.eclipse.core.resources/restore/syncinfo" value="false"/>

+<mapEntry key="org.eclipse.core.resources/restore/tree" value="false"/>

+<mapEntry key="org.eclipse.core.resources/save" value="false"/>

+<mapEntry key="org.eclipse.core.resources/save/markers" value="false"/>

+<mapEntry key="org.eclipse.core.resources/save/mastertable" value="false"/>

+<mapEntry key="org.eclipse.core.resources/save/metainfo" value="false"/>

+<mapEntry key="org.eclipse.core.resources/save/syncinfo" value="false"/>

+<mapEntry key="org.eclipse.core.resources/save/tree" value="false"/>

+<mapEntry key="org.eclipse.core.resources/strings" value="false"/>

+<mapEntry key="org.eclipse.core.runtime/compatibility/debug" value="false"/>

+<mapEntry key="org.eclipse.core.runtime/debug" value="false"/>

+<mapEntry key="org.eclipse.core.runtime/debug/context" value="false"/>

+<mapEntry key="org.eclipse.core.runtime/perf" value="false"/>

+<mapEntry key="org.eclipse.core.runtime/perf/success" value="false"/>

+<mapEntry key="org.eclipse.core.runtime/preferences/plugin" value="false"/>

+<mapEntry key="org.eclipse.core.runtime/url/debug" value="false"/>

+<mapEntry key="org.eclipse.core.runtime/url/debug/cachecopy" value="false"/>

+<mapEntry key="org.eclipse.core.runtime/url/debug/cachelookup" value="false"/>

+<mapEntry key="org.eclipse.core.runtime/url/debug/connect" value="false"/>

+<mapEntry key="org.eclipse.debug.core/debug" value="false"/>

+<mapEntry key="org.eclipse.debug.core/debug/commands" value="false"/>

+<mapEntry key="org.eclipse.debug.core/debug/events" value="false"/>

+<mapEntry key="org.eclipse.debug.ui/debug" value="false"/>

+<mapEntry key="org.eclipse.debug.ui/debug/contextlaunching" value="false"/>

+<mapEntry key="org.eclipse.debug.ui/debug/launchhistory" value="false"/>

+<mapEntry key="org.eclipse.debug.ui/debug/viewers/contentProvider" value="false"/>

+<mapEntry key="org.eclipse.debug.ui/debug/viewers/deltas" value="false"/>

+<mapEntry key="org.eclipse.debug.ui/debug/viewers/model" value="false"/>

+<mapEntry key="org.eclipse.debug.ui/debug/viewers/updateSequence" value="false"/>

+<mapEntry key="org.eclipse.debug.ui/debug/viewers/viewer" value="false"/>

+<mapEntry key="org.eclipse.emf.cdo.common/debug" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo.common/debug.model" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo.common/debug.protocol" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo.common/debug.revision" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo.common/perf" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo.common/perf.revision" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo.common/perf.revision.reading" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo.common/perf.revision.writing" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo.examples/debug" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo.server.db/debug" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo.server/debug" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo.server/debug.protocol" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo.server/debug.repository" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo.server/debug.resource" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo.server/debug.revision" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo.server/debug.session" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo.server/debug.store" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo.server/debug.types" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo.ui/debug" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo/debug" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo/debug.adapter" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo/debug.model" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo/debug.object" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo/debug.protocol" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo/debug.repository" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo/debug.resource" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo/debug.revision" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo/debug.session" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo/debug.transaction" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo/debug.util" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo/debug.view" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo/perf" value="false"/>

+<mapEntry key="org.eclipse.emf.cdo/perf.revision" value="false"/>

+<mapEntry key="org.eclipse.emf.cdo/perf.revision.loading" value="false"/>

+<mapEntry key="org.eclipse.equinox.preferences/general" value="false"/>

+<mapEntry key="org.eclipse.equinox.preferences/get" value="false"/>

+<mapEntry key="org.eclipse.equinox.preferences/set" value="false"/>

+<mapEntry key="org.eclipse.equinox.registry/debug" value="false"/>

+<mapEntry key="org.eclipse.equinox.registry/debug/events" value="false"/>

+<mapEntry key="org.eclipse.help.base/debug" value="true"/>

+<mapEntry key="org.eclipse.help.base/debug/search" value="false"/>

+<mapEntry key="org.eclipse.help.ui/debug" value="true"/>

+<mapEntry key="org.eclipse.help.ui/debug/embeddedBrowser" value="false"/>

+<mapEntry key="org.eclipse.help.ui/debug/embeddedBrowser/inprocess" value="false"/>

+<mapEntry key="org.eclipse.help.ui/debug/infopop" value="false"/>

+<mapEntry key="org.eclipse.help.webapp/debug" value="true"/>

+<mapEntry key="org.eclipse.help.webapp/debug/workingsets" value="false"/>

+<mapEntry key="org.eclipse.help/debug" value="true"/>

+<mapEntry key="org.eclipse.help/debug/context" value="false"/>

+<mapEntry key="org.eclipse.help/debug/search" value="false"/>

+<mapEntry key="org.eclipse.jdt.core.manipulation/debug" value="true"/>

+<mapEntry key="org.eclipse.jdt.core/debug" value="true"/>

+<mapEntry key="org.eclipse.jdt.core/debug/buffermanager" value="false"/>

+<mapEntry key="org.eclipse.jdt.core/debug/builder" value="false"/>

+<mapEntry key="org.eclipse.jdt.core/debug/compiler" value="false"/>

+<mapEntry key="org.eclipse.jdt.core/debug/completion" value="false"/>

+<mapEntry key="org.eclipse.jdt.core/debug/cpresolution" value="false"/>

+<mapEntry key="org.eclipse.jdt.core/debug/cpresolution/advanced" value="false"/>

+<mapEntry key="org.eclipse.jdt.core/debug/hierarchy" value="false"/>

+<mapEntry key="org.eclipse.jdt.core/debug/indexmanager" value="false"/>

+<mapEntry key="org.eclipse.jdt.core/debug/javadelta" value="false"/>

+<mapEntry key="org.eclipse.jdt.core/debug/javadelta/verbose" value="false"/>

+<mapEntry key="org.eclipse.jdt.core/debug/javamodel" value="false"/>

+<mapEntry key="org.eclipse.jdt.core/debug/javamodel/cache" value="false"/>

+<mapEntry key="org.eclipse.jdt.core/debug/postaction" value="false"/>

+<mapEntry key="org.eclipse.jdt.core/debug/resolution" value="false"/>

+<mapEntry key="org.eclipse.jdt.core/debug/search" value="false"/>

+<mapEntry key="org.eclipse.jdt.core/debug/selection" value="false"/>

+<mapEntry key="org.eclipse.jdt.core/debug/sourcemapper" value="false"/>

+<mapEntry key="org.eclipse.jdt.core/debug/zipaccess" value="false"/>

+<mapEntry key="org.eclipse.jdt.core/perf/completion" value="300"/>

+<mapEntry key="org.eclipse.jdt.core/perf/containerinitializer" value="5000"/>

+<mapEntry key="org.eclipse.jdt.core/perf/javadeltalistener" value="500"/>

+<mapEntry key="org.eclipse.jdt.core/perf/reconcile" value="1000"/>

+<mapEntry key="org.eclipse.jdt.core/perf/selection" value="300"/>

+<mapEntry key="org.eclipse.jdt.core/perf/variableinitializer" value="5000"/>

+<mapEntry key="org.eclipse.jdt.ui/debug" value="true"/>

+<mapEntry key="org.eclipse.jdt.ui/debug/ASTProvider" value="false"/>

+<mapEntry key="org.eclipse.jdt.ui/debug/ResultCollector" value="false"/>

+<mapEntry key="org.eclipse.jdt.ui/debug/TypeConstraints" value="false"/>

+<mapEntry key="org.eclipse.jdt.ui/perf/content_assist/extensions" value="1000"/>

+<mapEntry key="org.eclipse.jdt.ui/perf/content_assist_sorters/extensions" value=""/>

+<mapEntry key="org.eclipse.jdt.ui/perf/explorer/RefactorActionGroup" value="150"/>

+<mapEntry key="org.eclipse.jdt.ui/perf/explorer/createPartControl" value="1300"/>

+<mapEntry key="org.eclipse.jdt.ui/perf/explorer/makeActions" value="1000"/>

+<mapEntry key="org.eclipse.jdt.ui/perf/search/participants" value="300"/>

+<mapEntry key="org.eclipse.jface.text.source/debug/RevisionRulerColumn" value="false"/>

+<mapEntry key="org.eclipse.jface.text/debug/AnnotationPainter" value="false"/>

+<mapEntry key="org.eclipse.jface.text/debug/ContentAssistSubjectAdapters" value="false"/>

+<mapEntry key="org.eclipse.jface.text/debug/FastPartitioner/PositionCache" value="false"/>

+<mapEntry key="org.eclipse.ltk.core.refactoring/perf/participants/checkConditions" value="300"/>

+<mapEntry key="org.eclipse.ltk.core.refactoring/perf/participants/createChanges" value="300"/>

+<mapEntry key="org.eclipse.net4j.buddies.chat.ui/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.buddies.chat/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.buddies.common/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.buddies.server/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.buddies.ui/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.buddies/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.db.derby/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.db.derby/debug.sql" value="true"/>

+<mapEntry key="org.eclipse.net4j.db.hsqldb/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.db.hsqldb/debug.sql" value="true"/>

+<mapEntry key="org.eclipse.net4j.db.mysql/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.db.mysql/debug.sql" value="true"/>

+<mapEntry key="org.eclipse.net4j.db/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.db/debug.sql" value="true"/>

+<mapEntry key="org.eclipse.net4j.debug/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.examples/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.fileshare.ui/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.fileshare/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.jms.admin/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.jms.admin/debug.protocol" value="true"/>

+<mapEntry key="org.eclipse.net4j.jms.server.jdbc/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.jms.server/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.jms.server/debug.protocol" value="true"/>

+<mapEntry key="org.eclipse.net4j.jms.server/debug.store" value="true"/>

+<mapEntry key="org.eclipse.net4j.jms/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.jms/debug.protocol" value="true"/>

+<mapEntry key="org.eclipse.net4j.jvm/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.tcp/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.ui/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.util.ui/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.util/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.util/debug.concurrency" value="true"/>

+<mapEntry key="org.eclipse.net4j.util/debug.lifecycle" value="true"/>

+<mapEntry key="org.eclipse.net4j.util/debug.lifecycle.dump" value="true"/>

+<mapEntry key="org.eclipse.net4j.util/debug.om" value="true"/>

+<mapEntry key="org.eclipse.net4j.util/debug.registry" value="true"/>

+<mapEntry key="org.eclipse.net4j/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j/debug.acceptor" value="true"/>

+<mapEntry key="org.eclipse.net4j/debug.buffer" value="true"/>

+<mapEntry key="org.eclipse.net4j/debug.buffer.stream" value="false"/>

+<mapEntry key="org.eclipse.net4j/debug.channel" value="true"/>

+<mapEntry key="org.eclipse.net4j/debug.connector" value="true"/>

+<mapEntry key="org.eclipse.net4j/debug.selector" value="true"/>

+<mapEntry key="org.eclipse.net4j/debug.signal" value="true"/>

+<mapEntry key="org.eclipse.net4j/perf" value="false"/>

+<mapEntry key="org.eclipse.osgi/debug" value="false"/>

+<mapEntry key="org.eclipse.osgi/debug/bundleTime" value="false"/>

+<mapEntry key="org.eclipse.osgi/debug/events" value="false"/>

+<mapEntry key="org.eclipse.osgi/debug/filter" value="false"/>

+<mapEntry key="org.eclipse.osgi/debug/loader" value="false"/>

+<mapEntry key="org.eclipse.osgi/debug/manifest" value="false"/>

+<mapEntry key="org.eclipse.osgi/debug/messageBundles" value="false"/>

+<mapEntry key="org.eclipse.osgi/debug/packageadmin" value="false"/>

+<mapEntry key="org.eclipse.osgi/debug/security" value="false"/>

+<mapEntry key="org.eclipse.osgi/debug/services" value="false"/>

+<mapEntry key="org.eclipse.osgi/debug/startlevel" value="false"/>

+<mapEntry key="org.eclipse.osgi/defaultprofile/buffersize" value="256"/>

+<mapEntry key="org.eclipse.osgi/defaultprofile/logfilename" value=""/>

+<mapEntry key="org.eclipse.osgi/defaultprofile/logsynchronously" value="false"/>

+<mapEntry key="org.eclipse.osgi/eclipseadaptor/converter/debug" value="false"/>

+<mapEntry key="org.eclipse.osgi/eclipseadaptor/debug" value="false"/>

+<mapEntry key="org.eclipse.osgi/eclipseadaptor/debug/location" value="false"/>

+<mapEntry key="org.eclipse.osgi/eclipseadaptor/debug/platformadmin" value="false"/>

+<mapEntry key="org.eclipse.osgi/eclipseadaptor/debug/platformadmin/resolver" value="false"/>

+<mapEntry key="org.eclipse.osgi/monitor/activation" value="false"/>

+<mapEntry key="org.eclipse.osgi/monitor/classes" value="false"/>

+<mapEntry key="org.eclipse.osgi/monitor/resources" value="false"/>

+<mapEntry key="org.eclipse.osgi/profile/benchmark" value="false"/>

+<mapEntry key="org.eclipse.osgi/profile/debug" value="false"/>

+<mapEntry key="org.eclipse.osgi/profile/impl" value="org.eclipse.osgi.internal.profile.DefaultProfileLogger"/>

+<mapEntry key="org.eclipse.osgi/profile/startup" value="false"/>

+<mapEntry key="org.eclipse.osgi/resolver/cycles" value="false"/>

+<mapEntry key="org.eclipse.osgi/resolver/debug" value="false"/>

+<mapEntry key="org.eclipse.osgi/resolver/generics" value="false"/>

+<mapEntry key="org.eclipse.osgi/resolver/grouping" value="false"/>

+<mapEntry key="org.eclipse.osgi/resolver/imports" value="false"/>

+<mapEntry key="org.eclipse.osgi/resolver/requires" value="false"/>

+<mapEntry key="org.eclipse.osgi/resolver/wiring" value="false"/>

+<mapEntry key="org.eclipse.osgi/trace/activation" value="false"/>

+<mapEntry key="org.eclipse.osgi/trace/classLoading" value="false"/>

+<mapEntry key="org.eclipse.osgi/trace/filename" value="runtime.traces"/>

+<mapEntry key="org.eclipse.osgi/trace/filters" value="trace.properties"/>

+<mapEntry key="org.eclipse.pde.build/debug" value="false"/>

+<mapEntry key="org.eclipse.pde.core/cache" value="false"/>

+<mapEntry key="org.eclipse.pde.core/classpath" value="false"/>

+<mapEntry key="org.eclipse.pde.core/debug" value="true"/>

+<mapEntry key="org.eclipse.pde.core/validation" value="false"/>

+<mapEntry key="org.eclipse.team.core/backgroundevents" value="false"/>

+<mapEntry key="org.eclipse.team.core/debug" value="false"/>

+<mapEntry key="org.eclipse.team.core/refreshjob" value="false"/>

+<mapEntry key="org.eclipse.team.core/streams" value="false"/>

+<mapEntry key="org.eclipse.team.core/threading" value="false"/>

+<mapEntry key="org.eclipse.team.cvs.core/cvsprotocol" value="true"/>

+<mapEntry key="org.eclipse.team.cvs.core/debug" value="false"/>

+<mapEntry key="org.eclipse.team.cvs.core/dirtycaching" value="false"/>

+<mapEntry key="org.eclipse.team.cvs.core/metafiles" value="false"/>

+<mapEntry key="org.eclipse.team.cvs.core/syncchangeevents" value="false"/>

+<mapEntry key="org.eclipse.team.cvs.core/threading" value="false"/>

+<mapEntry key="org.eclipse.team.cvs.ssh/debug" value="false"/>

+<mapEntry key="org.eclipse.team.cvs.ssh/ssh_protocol" value="false"/>

+<mapEntry key="org.eclipse.ui.browser/debug" value="false"/>

+<mapEntry key="org.eclipse.ui.ide/debug" value="false"/>

+<mapEntry key="org.eclipse.ui.ide/debug/gc" value="false"/>

+<mapEntry key="org.eclipse.ui.ide/debug/internalerror/openDialog" value="false"/>

+<mapEntry key="org.eclipse.ui.ide/debug/undomonitor" value="false"/>

+<mapEntry key="org.eclipse.ui.intro.universal/debug" value="true"/>

+<mapEntry key="org.eclipse.ui.intro.universal/trace/logInfo" value="true"/>

+<mapEntry key="org.eclipse.ui.intro.universal/trace/logPerformance" value="false"/>

+<mapEntry key="org.eclipse.ui.intro/debug" value="true"/>

+<mapEntry key="org.eclipse.ui.intro/flags/noBrowser" value="false"/>

+<mapEntry key="org.eclipse.ui.intro/trace/logInfo" value="true"/>

+<mapEntry key="org.eclipse.ui.intro/trace/logPerformance" value="false"/>

+<mapEntry key="org.eclipse.ui.intro/trace/printHTML" value="false"/>

+<mapEntry key="org.eclipse.ui.workbench/debug" value="false"/>

+<mapEntry key="org.eclipse.ui/debug" value="false"/>

+<mapEntry key="org.eclipse.ui/debug/contributions" value="false"/>

+<mapEntry key="org.eclipse.ui/debug/declaredImages" value="false"/>

+<mapEntry key="org.eclipse.ui/debug/job.stale" value="false"/>

+<mapEntry key="org.eclipse.ui/debug/showAllJobs" value="false"/>

+<mapEntry key="org.eclipse.ui/debug/swtdebug" value="false"/>

+<mapEntry key="org.eclipse.ui/debug/workingSets" value="false"/>

+<mapEntry key="org.eclipse.ui/experimental/menus" value="false"/>

+<mapEntry key="org.eclipse.ui/listeners/IWorkbenchPage.IPartListener" value="false"/>

+<mapEntry key="org.eclipse.ui/listeners/IWorkbenchPage.IPartListener2" value="false"/>

+<mapEntry key="org.eclipse.ui/listeners/IWorkbenchPage.IPropertyChangeListener" value="false"/>

+<mapEntry key="org.eclipse.ui/listeners/IWorkbenchPartReference" value="false"/>

+<mapEntry key="org.eclipse.ui/listeners/IWorkbenchWindow.IPageListener" value="false"/>

+<mapEntry key="org.eclipse.ui/listeners/IWorkbenchWindow.IPartListener" value="false"/>

+<mapEntry key="org.eclipse.ui/listeners/IWorkbenchWindow.IPartListener2" value="false"/>

+<mapEntry key="org.eclipse.ui/listeners/IWorkbenchWindow.IPerspectiveListener" value="false"/>

+<mapEntry key="org.eclipse.ui/perf/contentTypes" value="200"/>

+<mapEntry key="org.eclipse.ui/perf/page.listeners" value="200"/>

+<mapEntry key="org.eclipse.ui/perf/part.activate" value="200"/>

+<mapEntry key="org.eclipse.ui/perf/part.control" value="800"/>

+<mapEntry key="org.eclipse.ui/perf/part.create" value="800"/>

+<mapEntry key="org.eclipse.ui/perf/part.init" value="800"/>

+<mapEntry key="org.eclipse.ui/perf/part.input" value="200"/>

+<mapEntry key="org.eclipse.ui/perf/part.listeners" value="200"/>

+<mapEntry key="org.eclipse.ui/perf/perspective.create" value="800"/>

+<mapEntry key="org.eclipse.ui/perf/perspective.listeners" value="200"/>

+<mapEntry key="org.eclipse.ui/perf/perspective.switch" value="800"/>

+<mapEntry key="org.eclipse.ui/perf/showHeapStatus" value="true"/>

+<mapEntry key="org.eclipse.ui/perf/uijob" value="200"/>

+<mapEntry key="org.eclipse.ui/perf/workbench.restore" value="30000"/>

+<mapEntry key="org.eclipse.ui/perf/workbench.start" value="45000"/>

+<mapEntry key="org.eclipse.ui/trace/commands" value="false"/>

+<mapEntry key="org.eclipse.ui/trace/contexts" value="false"/>

+<mapEntry key="org.eclipse.ui/trace/contexts.performance" value="false"/>

+<mapEntry key="org.eclipse.ui/trace/contexts.verbose" value="false"/>

+<mapEntry key="org.eclipse.ui/trace/graphics" value="false"/>

+<mapEntry key="org.eclipse.ui/trace/handlers" value="false"/>

+<mapEntry key="org.eclipse.ui/trace/handlers.performance" value="false"/>

+<mapEntry key="org.eclipse.ui/trace/handlers.verbose" value="false"/>

+<mapEntry key="org.eclipse.ui/trace/handlers.verbose.commandId" value=""/>

+<mapEntry key="org.eclipse.ui/trace/keyBindings" value="false"/>

+<mapEntry key="org.eclipse.ui/trace/keyBindings.verbose" value="false"/>

+<mapEntry key="org.eclipse.ui/trace/multipageeditor" value="false"/>

+<mapEntry key="org.eclipse.ui/trace/operations" value="false"/>

+<mapEntry key="org.eclipse.ui/trace/operations.verbose" value="false"/>

+<mapEntry key="org.eclipse.ui/trace/sources" value="false"/>

+<mapEntry key="org.eclipse.update.configurator/debug" value="false"/>

+<mapEntry key="org.eclipse.update.core/debug" value="true"/>

+<mapEntry key="org.eclipse.update.core/debug/configuration" value="false"/>

+<mapEntry key="org.eclipse.update.core/debug/install" value="false"/>

+<mapEntry key="org.eclipse.update.core/debug/installhandler" value="false"/>

+<mapEntry key="org.eclipse.update.core/debug/parsing" value="false"/>

+<mapEntry key="org.eclipse.update.core/debug/reconciler" value="false"/>

+<mapEntry key="org.eclipse.update.core/debug/type" value="false"/>

+<mapEntry key="org.eclipse.update.core/debug/warning" value="false"/>

+<mapEntry key="org.eclipse.update.core/debug/web" value="false"/>

+</mapAttribute>

+<booleanAttribute key="useCustomFeatures" value="false"/>

+<booleanAttribute key="useDefaultConfig" value="true"/>

+<booleanAttribute key="useDefaultConfigArea" value="true"/>

+<booleanAttribute key="useNamedJRE" value="true"/>

+<booleanAttribute key="useProduct" value="false"/>

+<booleanAttribute key="usefeatures" value="false"/>

+</launchConfiguration>

diff --git a/org.eclipse.emf.cdo.server/CDOServer_SSL.launch b/org.eclipse.emf.cdo.server/CDOServer_SSL.launch
new file mode 100644
index 0000000..a668fd5
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/CDOServer_SSL.launch
@@ -0,0 +1,368 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>

+<launchConfiguration type="org.eclipse.pde.ui.RuntimeWorkbench">

+<booleanAttribute key="append.args" value="true"/>

+<stringAttribute key="application" value="org.eclipse.emf.cdo.server.app"/>

+<booleanAttribute key="askclear" value="true"/>

+<booleanAttribute key="automaticAdd" value="false"/>

+<booleanAttribute key="automaticValidate" value="false"/>

+<stringAttribute key="bootstrap" value=""/>

+<stringAttribute key="checked" value="org.eclipse.emf.cdo.server,org.eclipse.emf.cdo.server.db,org.eclipse.net4j,org.eclipse.net4j.db,org.eclipse.net4j.db.derby,org.eclipse.net4j.http.common,org.eclipse.net4j.http.server,org.eclipse.net4j.tcp,org.eclipse.net4j.util"/>

+<booleanAttribute key="clearConfig" value="true"/>

+<booleanAttribute key="clearws" value="false"/>

+<booleanAttribute key="clearwslog" value="false"/>

+<stringAttribute key="configLocation" value="${workspace_loc}/.metadata/.plugins/org.eclipse.pde.core/CDOServer_SSL"/>

+<booleanAttribute key="default" value="false"/>

+<booleanAttribute key="includeOptional" value="true"/>

+<stringAttribute key="location" value="${workspace_loc}/../cdo.server"/>

+<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/>

+<mapAttribute key="org.eclipse.debug.core.preferred_launchers">

+<mapEntry key="[run]" value="org.eclipse.pde.ui.RuntimeWorkbench"/>

+</mapAttribute>

+<listAttribute key="org.eclipse.debug.ui.favoriteGroups">

+<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>

+<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>

+</listAttribute>

+<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>

+<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl}&#13;&#10;-debug&#13;&#10;-console"/>

+<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.pde.ui.workbenchClasspathProvider"/>

+<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xms40m&#13;&#10;-Xmx1024m&#13;&#10;-Ddebug=true&#13;&#10;-Dnet4j.config=&quot;${resource_loc:/org.eclipse.emf.cdo.server.product-feature/rootfiles/configuration-ssl}&quot;&#13;&#10;-Dorg.eclipse.net4j.tcp.ssl.passphrase=ab987c&#10;-Dorg.eclipse.net4j.tcp.ssl.trust=file:///${workspace_loc:org.eclipse.emf.cdo.server}/sslKey/testTrust&#10;-Dorg.eclipse.net4j.tcp.ssl.key=file:///${workspace_loc:org.eclipse.emf.cdo.server}/sslKey/testKeys&#10;-Dorg.eclipse.emf.cdo.server.browser.port=7777&#13;&#10;-Dorg.osgi.service.http.port=8080"/>

+<stringAttribute key="pde.version" value="3.3"/>

+<stringAttribute key="product" value="org.eclipse.platform.ide"/>

+<stringAttribute key="selectedPlugin" value="org.eclipse.emf.cdo"/>

+<stringAttribute key="selected_target_plugins" value="com.mysql.jdbc@default:default,javax.servlet@default:default,org.apache.derby@default:default,org.eclipse.ant.core@default:default,org.eclipse.core.contenttype@default:default,org.eclipse.core.expressions@default:default,org.eclipse.core.filesystem.win32.x86_64@default:false,org.eclipse.core.filesystem@default:default,org.eclipse.core.jobs@default:default,org.eclipse.core.resources@default:default,org.eclipse.core.runtime.compatibility.auth@default:default,org.eclipse.core.runtime.compatibility.registry@default:false,org.eclipse.core.runtime@default:true,org.eclipse.core.variables@default:default,org.eclipse.emf.common@default:default,org.eclipse.emf.ecore.change@default:default,org.eclipse.emf.ecore.xmi@default:default,org.eclipse.emf.ecore@default:default,org.eclipse.equinox.app@default:default,org.eclipse.equinox.common@2:true,org.eclipse.equinox.preferences@default:default,org.eclipse.equinox.registry@default:default,org.eclipse.osgi.services@default:default,org.eclipse.osgi@-1:true,org.h2@default:default,org.hsqldb@default:default,org.postgresql.jdbc3@default:default"/>

+<stringAttribute key="selected_workspace_plugins" value="org.eclipse.emf.cdo.common@default:default,org.eclipse.emf.cdo.server.db@default:default,org.eclipse.emf.cdo.server.net4j@default:default,org.eclipse.emf.cdo.server@default:default,org.eclipse.emf.cdo@default:default,org.eclipse.net4j.db.derby@default:default,org.eclipse.net4j.db.h2@default:default,org.eclipse.net4j.db.hsqldb@default:default,org.eclipse.net4j.db.mysql@default:default,org.eclipse.net4j.db.postgresql@default:default,org.eclipse.net4j.db@default:default,org.eclipse.net4j.tcp@default:default,org.eclipse.net4j.util@default:default,org.eclipse.net4j@default:default"/>

+<booleanAttribute key="show_selected_only" value="true"/>

+<stringAttribute key="templateConfig" value="${target_home}\configuration\config.ini"/>

+<booleanAttribute key="tracing" value="true"/>

+<mapAttribute key="tracingOptions">

+<mapEntry key="org.eclipse.core.contenttype/debug" value="false"/>

+<mapEntry key="org.eclipse.core.expressions/tracePropertyResolving" value="false"/>

+<mapEntry key="org.eclipse.core.jobs/jobs" value="false"/>

+<mapEntry key="org.eclipse.core.jobs/jobs/beginend" value="false"/>

+<mapEntry key="org.eclipse.core.jobs/jobs/errorondeadlock" value="false"/>

+<mapEntry key="org.eclipse.core.jobs/jobs/locks" value="false"/>

+<mapEntry key="org.eclipse.core.jobs/jobs/shutdown" value="false"/>

+<mapEntry key="org.eclipse.core.jobs/jobs/timing" value="false"/>

+<mapEntry key="org.eclipse.core.resources/build/delta" value="false"/>

+<mapEntry key="org.eclipse.core.resources/build/failure" value="false"/>

+<mapEntry key="org.eclipse.core.resources/build/interrupt" value="false"/>

+<mapEntry key="org.eclipse.core.resources/build/invoking" value="false"/>

+<mapEntry key="org.eclipse.core.resources/build/needbuild" value="false"/>

+<mapEntry key="org.eclipse.core.resources/build/needbuildstack" value="false"/>

+<mapEntry key="org.eclipse.core.resources/build/stacktrace" value="false"/>

+<mapEntry key="org.eclipse.core.resources/contenttype" value="false"/>

+<mapEntry key="org.eclipse.core.resources/contenttype/cache" value="false"/>

+<mapEntry key="org.eclipse.core.resources/debug" value="false"/>

+<mapEntry key="org.eclipse.core.resources/history" value="false"/>

+<mapEntry key="org.eclipse.core.resources/natures" value="false"/>

+<mapEntry key="org.eclipse.core.resources/perf/builders" value="10000"/>

+<mapEntry key="org.eclipse.core.resources/perf/listeners" value="500"/>

+<mapEntry key="org.eclipse.core.resources/perf/save.participants" value="500"/>

+<mapEntry key="org.eclipse.core.resources/perf/snapshot" value="1000"/>

+<mapEntry key="org.eclipse.core.resources/preferences" value="false"/>

+<mapEntry key="org.eclipse.core.resources/refresh" value="false"/>

+<mapEntry key="org.eclipse.core.resources/restore" value="false"/>

+<mapEntry key="org.eclipse.core.resources/restore/markers" value="false"/>

+<mapEntry key="org.eclipse.core.resources/restore/mastertable" value="false"/>

+<mapEntry key="org.eclipse.core.resources/restore/metainfo" value="false"/>

+<mapEntry key="org.eclipse.core.resources/restore/snapshots" value="false"/>

+<mapEntry key="org.eclipse.core.resources/restore/syncinfo" value="false"/>

+<mapEntry key="org.eclipse.core.resources/restore/tree" value="false"/>

+<mapEntry key="org.eclipse.core.resources/save" value="false"/>

+<mapEntry key="org.eclipse.core.resources/save/markers" value="false"/>

+<mapEntry key="org.eclipse.core.resources/save/mastertable" value="false"/>

+<mapEntry key="org.eclipse.core.resources/save/metainfo" value="false"/>

+<mapEntry key="org.eclipse.core.resources/save/syncinfo" value="false"/>

+<mapEntry key="org.eclipse.core.resources/save/tree" value="false"/>

+<mapEntry key="org.eclipse.core.resources/strings" value="false"/>

+<mapEntry key="org.eclipse.core.runtime/compatibility/debug" value="false"/>

+<mapEntry key="org.eclipse.core.runtime/debug" value="false"/>

+<mapEntry key="org.eclipse.core.runtime/debug/context" value="false"/>

+<mapEntry key="org.eclipse.core.runtime/perf" value="false"/>

+<mapEntry key="org.eclipse.core.runtime/perf/success" value="false"/>

+<mapEntry key="org.eclipse.core.runtime/preferences/plugin" value="false"/>

+<mapEntry key="org.eclipse.core.runtime/url/debug" value="false"/>

+<mapEntry key="org.eclipse.core.runtime/url/debug/cachecopy" value="false"/>

+<mapEntry key="org.eclipse.core.runtime/url/debug/cachelookup" value="false"/>

+<mapEntry key="org.eclipse.core.runtime/url/debug/connect" value="false"/>

+<mapEntry key="org.eclipse.debug.core/debug" value="false"/>

+<mapEntry key="org.eclipse.debug.core/debug/commands" value="false"/>

+<mapEntry key="org.eclipse.debug.core/debug/events" value="false"/>

+<mapEntry key="org.eclipse.debug.ui/debug" value="false"/>

+<mapEntry key="org.eclipse.debug.ui/debug/contextlaunching" value="false"/>

+<mapEntry key="org.eclipse.debug.ui/debug/launchhistory" value="false"/>

+<mapEntry key="org.eclipse.debug.ui/debug/viewers/contentProvider" value="false"/>

+<mapEntry key="org.eclipse.debug.ui/debug/viewers/deltas" value="false"/>

+<mapEntry key="org.eclipse.debug.ui/debug/viewers/model" value="false"/>

+<mapEntry key="org.eclipse.debug.ui/debug/viewers/updateSequence" value="false"/>

+<mapEntry key="org.eclipse.debug.ui/debug/viewers/viewer" value="false"/>

+<mapEntry key="org.eclipse.emf.cdo.common/debug" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo.common/debug.model" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo.common/debug.protocol" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo.common/debug.revision" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo.common/perf" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo.common/perf.revision" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo.common/perf.revision.reading" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo.common/perf.revision.writing" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo.examples/debug" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo.server.db/debug" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo.server/debug" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo.server/debug.protocol" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo.server/debug.repository" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo.server/debug.resource" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo.server/debug.revision" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo.server/debug.session" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo.server/debug.store" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo.server/debug.types" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo.ui/debug" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo/debug" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo/debug.adapter" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo/debug.model" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo/debug.object" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo/debug.protocol" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo/debug.repository" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo/debug.resource" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo/debug.revision" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo/debug.session" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo/debug.transaction" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo/debug.util" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo/debug.view" value="true"/>

+<mapEntry key="org.eclipse.emf.cdo/perf" value="false"/>

+<mapEntry key="org.eclipse.emf.cdo/perf.revision" value="false"/>

+<mapEntry key="org.eclipse.emf.cdo/perf.revision.loading" value="false"/>

+<mapEntry key="org.eclipse.equinox.preferences/general" value="false"/>

+<mapEntry key="org.eclipse.equinox.preferences/get" value="false"/>

+<mapEntry key="org.eclipse.equinox.preferences/set" value="false"/>

+<mapEntry key="org.eclipse.equinox.registry/debug" value="false"/>

+<mapEntry key="org.eclipse.equinox.registry/debug/events" value="false"/>

+<mapEntry key="org.eclipse.help.base/debug" value="true"/>

+<mapEntry key="org.eclipse.help.base/debug/search" value="false"/>

+<mapEntry key="org.eclipse.help.ui/debug" value="true"/>

+<mapEntry key="org.eclipse.help.ui/debug/embeddedBrowser" value="false"/>

+<mapEntry key="org.eclipse.help.ui/debug/embeddedBrowser/inprocess" value="false"/>

+<mapEntry key="org.eclipse.help.ui/debug/infopop" value="false"/>

+<mapEntry key="org.eclipse.help.webapp/debug" value="true"/>

+<mapEntry key="org.eclipse.help.webapp/debug/workingsets" value="false"/>

+<mapEntry key="org.eclipse.help/debug" value="true"/>

+<mapEntry key="org.eclipse.help/debug/context" value="false"/>

+<mapEntry key="org.eclipse.help/debug/search" value="false"/>

+<mapEntry key="org.eclipse.jdt.core.manipulation/debug" value="true"/>

+<mapEntry key="org.eclipse.jdt.core/debug" value="true"/>

+<mapEntry key="org.eclipse.jdt.core/debug/buffermanager" value="false"/>

+<mapEntry key="org.eclipse.jdt.core/debug/builder" value="false"/>

+<mapEntry key="org.eclipse.jdt.core/debug/compiler" value="false"/>

+<mapEntry key="org.eclipse.jdt.core/debug/completion" value="false"/>

+<mapEntry key="org.eclipse.jdt.core/debug/cpresolution" value="false"/>

+<mapEntry key="org.eclipse.jdt.core/debug/cpresolution/advanced" value="false"/>

+<mapEntry key="org.eclipse.jdt.core/debug/hierarchy" value="false"/>

+<mapEntry key="org.eclipse.jdt.core/debug/indexmanager" value="false"/>

+<mapEntry key="org.eclipse.jdt.core/debug/javadelta" value="false"/>

+<mapEntry key="org.eclipse.jdt.core/debug/javadelta/verbose" value="false"/>

+<mapEntry key="org.eclipse.jdt.core/debug/javamodel" value="false"/>

+<mapEntry key="org.eclipse.jdt.core/debug/javamodel/cache" value="false"/>

+<mapEntry key="org.eclipse.jdt.core/debug/postaction" value="false"/>

+<mapEntry key="org.eclipse.jdt.core/debug/resolution" value="false"/>

+<mapEntry key="org.eclipse.jdt.core/debug/search" value="false"/>

+<mapEntry key="org.eclipse.jdt.core/debug/selection" value="false"/>

+<mapEntry key="org.eclipse.jdt.core/debug/sourcemapper" value="false"/>

+<mapEntry key="org.eclipse.jdt.core/debug/zipaccess" value="false"/>

+<mapEntry key="org.eclipse.jdt.core/perf/completion" value="300"/>

+<mapEntry key="org.eclipse.jdt.core/perf/containerinitializer" value="5000"/>

+<mapEntry key="org.eclipse.jdt.core/perf/javadeltalistener" value="500"/>

+<mapEntry key="org.eclipse.jdt.core/perf/reconcile" value="1000"/>

+<mapEntry key="org.eclipse.jdt.core/perf/selection" value="300"/>

+<mapEntry key="org.eclipse.jdt.core/perf/variableinitializer" value="5000"/>

+<mapEntry key="org.eclipse.jdt.ui/debug" value="true"/>

+<mapEntry key="org.eclipse.jdt.ui/debug/ASTProvider" value="false"/>

+<mapEntry key="org.eclipse.jdt.ui/debug/ResultCollector" value="false"/>

+<mapEntry key="org.eclipse.jdt.ui/debug/TypeConstraints" value="false"/>

+<mapEntry key="org.eclipse.jdt.ui/perf/content_assist/extensions" value="1000"/>

+<mapEntry key="org.eclipse.jdt.ui/perf/content_assist_sorters/extensions" value=""/>

+<mapEntry key="org.eclipse.jdt.ui/perf/explorer/RefactorActionGroup" value="150"/>

+<mapEntry key="org.eclipse.jdt.ui/perf/explorer/createPartControl" value="1300"/>

+<mapEntry key="org.eclipse.jdt.ui/perf/explorer/makeActions" value="1000"/>

+<mapEntry key="org.eclipse.jdt.ui/perf/search/participants" value="300"/>

+<mapEntry key="org.eclipse.jface.text.source/debug/RevisionRulerColumn" value="false"/>

+<mapEntry key="org.eclipse.jface.text/debug/AnnotationPainter" value="false"/>

+<mapEntry key="org.eclipse.jface.text/debug/ContentAssistSubjectAdapters" value="false"/>

+<mapEntry key="org.eclipse.jface.text/debug/FastPartitioner/PositionCache" value="false"/>

+<mapEntry key="org.eclipse.ltk.core.refactoring/perf/participants/checkConditions" value="300"/>

+<mapEntry key="org.eclipse.ltk.core.refactoring/perf/participants/createChanges" value="300"/>

+<mapEntry key="org.eclipse.net4j.buddies.chat.ui/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.buddies.chat/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.buddies.common/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.buddies.server/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.buddies.ui/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.buddies/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.db.derby/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.db.derby/debug.sql" value="true"/>

+<mapEntry key="org.eclipse.net4j.db.hsqldb/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.db.hsqldb/debug.sql" value="true"/>

+<mapEntry key="org.eclipse.net4j.db.mysql/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.db.mysql/debug.sql" value="true"/>

+<mapEntry key="org.eclipse.net4j.db/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.db/debug.sql" value="true"/>

+<mapEntry key="org.eclipse.net4j.debug/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.examples/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.fileshare.ui/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.fileshare/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.jms.admin/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.jms.admin/debug.protocol" value="true"/>

+<mapEntry key="org.eclipse.net4j.jms.server.jdbc/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.jms.server/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.jms.server/debug.protocol" value="true"/>

+<mapEntry key="org.eclipse.net4j.jms.server/debug.store" value="true"/>

+<mapEntry key="org.eclipse.net4j.jms/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.jms/debug.protocol" value="true"/>

+<mapEntry key="org.eclipse.net4j.jvm/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.tcp/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.ui/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.util.ui/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.util/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j.util/debug.concurrency" value="true"/>

+<mapEntry key="org.eclipse.net4j.util/debug.lifecycle" value="true"/>

+<mapEntry key="org.eclipse.net4j.util/debug.lifecycle.dump" value="true"/>

+<mapEntry key="org.eclipse.net4j.util/debug.om" value="true"/>

+<mapEntry key="org.eclipse.net4j.util/debug.registry" value="true"/>

+<mapEntry key="org.eclipse.net4j/debug" value="true"/>

+<mapEntry key="org.eclipse.net4j/debug.acceptor" value="true"/>

+<mapEntry key="org.eclipse.net4j/debug.buffer" value="true"/>

+<mapEntry key="org.eclipse.net4j/debug.buffer.stream" value="false"/>

+<mapEntry key="org.eclipse.net4j/debug.channel" value="true"/>

+<mapEntry key="org.eclipse.net4j/debug.connector" value="true"/>

+<mapEntry key="org.eclipse.net4j/debug.selector" value="true"/>

+<mapEntry key="org.eclipse.net4j/debug.signal" value="true"/>

+<mapEntry key="org.eclipse.net4j/perf" value="false"/>

+<mapEntry key="org.eclipse.osgi/debug" value="false"/>

+<mapEntry key="org.eclipse.osgi/debug/bundleTime" value="false"/>

+<mapEntry key="org.eclipse.osgi/debug/events" value="false"/>

+<mapEntry key="org.eclipse.osgi/debug/filter" value="false"/>

+<mapEntry key="org.eclipse.osgi/debug/loader" value="false"/>

+<mapEntry key="org.eclipse.osgi/debug/manifest" value="false"/>

+<mapEntry key="org.eclipse.osgi/debug/messageBundles" value="false"/>

+<mapEntry key="org.eclipse.osgi/debug/packageadmin" value="false"/>

+<mapEntry key="org.eclipse.osgi/debug/security" value="false"/>

+<mapEntry key="org.eclipse.osgi/debug/services" value="false"/>

+<mapEntry key="org.eclipse.osgi/debug/startlevel" value="false"/>

+<mapEntry key="org.eclipse.osgi/defaultprofile/buffersize" value="256"/>

+<mapEntry key="org.eclipse.osgi/defaultprofile/logfilename" value=""/>

+<mapEntry key="org.eclipse.osgi/defaultprofile/logsynchronously" value="false"/>

+<mapEntry key="org.eclipse.osgi/eclipseadaptor/converter/debug" value="false"/>

+<mapEntry key="org.eclipse.osgi/eclipseadaptor/debug" value="false"/>

+<mapEntry key="org.eclipse.osgi/eclipseadaptor/debug/location" value="false"/>

+<mapEntry key="org.eclipse.osgi/eclipseadaptor/debug/platformadmin" value="false"/>

+<mapEntry key="org.eclipse.osgi/eclipseadaptor/debug/platformadmin/resolver" value="false"/>

+<mapEntry key="org.eclipse.osgi/monitor/activation" value="false"/>

+<mapEntry key="org.eclipse.osgi/monitor/classes" value="false"/>

+<mapEntry key="org.eclipse.osgi/monitor/resources" value="false"/>

+<mapEntry key="org.eclipse.osgi/profile/benchmark" value="false"/>

+<mapEntry key="org.eclipse.osgi/profile/debug" value="false"/>

+<mapEntry key="org.eclipse.osgi/profile/impl" value="org.eclipse.osgi.internal.profile.DefaultProfileLogger"/>

+<mapEntry key="org.eclipse.osgi/profile/startup" value="false"/>

+<mapEntry key="org.eclipse.osgi/resolver/cycles" value="false"/>

+<mapEntry key="org.eclipse.osgi/resolver/debug" value="false"/>

+<mapEntry key="org.eclipse.osgi/resolver/generics" value="false"/>

+<mapEntry key="org.eclipse.osgi/resolver/grouping" value="false"/>

+<mapEntry key="org.eclipse.osgi/resolver/imports" value="false"/>

+<mapEntry key="org.eclipse.osgi/resolver/requires" value="false"/>

+<mapEntry key="org.eclipse.osgi/resolver/wiring" value="false"/>

+<mapEntry key="org.eclipse.osgi/trace/activation" value="false"/>

+<mapEntry key="org.eclipse.osgi/trace/classLoading" value="false"/>

+<mapEntry key="org.eclipse.osgi/trace/filename" value="runtime.traces"/>

+<mapEntry key="org.eclipse.osgi/trace/filters" value="trace.properties"/>

+<mapEntry key="org.eclipse.pde.build/debug" value="false"/>

+<mapEntry key="org.eclipse.pde.core/cache" value="false"/>

+<mapEntry key="org.eclipse.pde.core/classpath" value="false"/>

+<mapEntry key="org.eclipse.pde.core/debug" value="true"/>

+<mapEntry key="org.eclipse.pde.core/validation" value="false"/>

+<mapEntry key="org.eclipse.team.core/backgroundevents" value="false"/>

+<mapEntry key="org.eclipse.team.core/debug" value="false"/>

+<mapEntry key="org.eclipse.team.core/refreshjob" value="false"/>

+<mapEntry key="org.eclipse.team.core/streams" value="false"/>

+<mapEntry key="org.eclipse.team.core/threading" value="false"/>

+<mapEntry key="org.eclipse.team.cvs.core/cvsprotocol" value="true"/>

+<mapEntry key="org.eclipse.team.cvs.core/debug" value="false"/>

+<mapEntry key="org.eclipse.team.cvs.core/dirtycaching" value="false"/>

+<mapEntry key="org.eclipse.team.cvs.core/metafiles" value="false"/>

+<mapEntry key="org.eclipse.team.cvs.core/syncchangeevents" value="false"/>

+<mapEntry key="org.eclipse.team.cvs.core/threading" value="false"/>

+<mapEntry key="org.eclipse.team.cvs.ssh/debug" value="false"/>

+<mapEntry key="org.eclipse.team.cvs.ssh/ssh_protocol" value="false"/>

+<mapEntry key="org.eclipse.ui.browser/debug" value="false"/>

+<mapEntry key="org.eclipse.ui.ide/debug" value="false"/>

+<mapEntry key="org.eclipse.ui.ide/debug/gc" value="false"/>

+<mapEntry key="org.eclipse.ui.ide/debug/internalerror/openDialog" value="false"/>

+<mapEntry key="org.eclipse.ui.ide/debug/undomonitor" value="false"/>

+<mapEntry key="org.eclipse.ui.intro.universal/debug" value="true"/>

+<mapEntry key="org.eclipse.ui.intro.universal/trace/logInfo" value="true"/>

+<mapEntry key="org.eclipse.ui.intro.universal/trace/logPerformance" value="false"/>

+<mapEntry key="org.eclipse.ui.intro/debug" value="true"/>

+<mapEntry key="org.eclipse.ui.intro/flags/noBrowser" value="false"/>

+<mapEntry key="org.eclipse.ui.intro/trace/logInfo" value="true"/>

+<mapEntry key="org.eclipse.ui.intro/trace/logPerformance" value="false"/>

+<mapEntry key="org.eclipse.ui.intro/trace/printHTML" value="false"/>

+<mapEntry key="org.eclipse.ui.workbench/debug" value="false"/>

+<mapEntry key="org.eclipse.ui/debug" value="false"/>

+<mapEntry key="org.eclipse.ui/debug/contributions" value="false"/>

+<mapEntry key="org.eclipse.ui/debug/declaredImages" value="false"/>

+<mapEntry key="org.eclipse.ui/debug/job.stale" value="false"/>

+<mapEntry key="org.eclipse.ui/debug/showAllJobs" value="false"/>

+<mapEntry key="org.eclipse.ui/debug/swtdebug" value="false"/>

+<mapEntry key="org.eclipse.ui/debug/workingSets" value="false"/>

+<mapEntry key="org.eclipse.ui/experimental/menus" value="false"/>

+<mapEntry key="org.eclipse.ui/listeners/IWorkbenchPage.IPartListener" value="false"/>

+<mapEntry key="org.eclipse.ui/listeners/IWorkbenchPage.IPartListener2" value="false"/>

+<mapEntry key="org.eclipse.ui/listeners/IWorkbenchPage.IPropertyChangeListener" value="false"/>

+<mapEntry key="org.eclipse.ui/listeners/IWorkbenchPartReference" value="false"/>

+<mapEntry key="org.eclipse.ui/listeners/IWorkbenchWindow.IPageListener" value="false"/>

+<mapEntry key="org.eclipse.ui/listeners/IWorkbenchWindow.IPartListener" value="false"/>

+<mapEntry key="org.eclipse.ui/listeners/IWorkbenchWindow.IPartListener2" value="false"/>

+<mapEntry key="org.eclipse.ui/listeners/IWorkbenchWindow.IPerspectiveListener" value="false"/>

+<mapEntry key="org.eclipse.ui/perf/contentTypes" value="200"/>

+<mapEntry key="org.eclipse.ui/perf/page.listeners" value="200"/>

+<mapEntry key="org.eclipse.ui/perf/part.activate" value="200"/>

+<mapEntry key="org.eclipse.ui/perf/part.control" value="800"/>

+<mapEntry key="org.eclipse.ui/perf/part.create" value="800"/>

+<mapEntry key="org.eclipse.ui/perf/part.init" value="800"/>

+<mapEntry key="org.eclipse.ui/perf/part.input" value="200"/>

+<mapEntry key="org.eclipse.ui/perf/part.listeners" value="200"/>

+<mapEntry key="org.eclipse.ui/perf/perspective.create" value="800"/>

+<mapEntry key="org.eclipse.ui/perf/perspective.listeners" value="200"/>

+<mapEntry key="org.eclipse.ui/perf/perspective.switch" value="800"/>

+<mapEntry key="org.eclipse.ui/perf/showHeapStatus" value="true"/>

+<mapEntry key="org.eclipse.ui/perf/uijob" value="200"/>

+<mapEntry key="org.eclipse.ui/perf/workbench.restore" value="30000"/>

+<mapEntry key="org.eclipse.ui/perf/workbench.start" value="45000"/>

+<mapEntry key="org.eclipse.ui/trace/commands" value="false"/>

+<mapEntry key="org.eclipse.ui/trace/contexts" value="false"/>

+<mapEntry key="org.eclipse.ui/trace/contexts.performance" value="false"/>

+<mapEntry key="org.eclipse.ui/trace/contexts.verbose" value="false"/>

+<mapEntry key="org.eclipse.ui/trace/graphics" value="false"/>

+<mapEntry key="org.eclipse.ui/trace/handlers" value="false"/>

+<mapEntry key="org.eclipse.ui/trace/handlers.performance" value="false"/>

+<mapEntry key="org.eclipse.ui/trace/handlers.verbose" value="false"/>

+<mapEntry key="org.eclipse.ui/trace/handlers.verbose.commandId" value=""/>

+<mapEntry key="org.eclipse.ui/trace/keyBindings" value="false"/>

+<mapEntry key="org.eclipse.ui/trace/keyBindings.verbose" value="false"/>

+<mapEntry key="org.eclipse.ui/trace/multipageeditor" value="false"/>

+<mapEntry key="org.eclipse.ui/trace/operations" value="false"/>

+<mapEntry key="org.eclipse.ui/trace/operations.verbose" value="false"/>

+<mapEntry key="org.eclipse.ui/trace/sources" value="false"/>

+<mapEntry key="org.eclipse.update.configurator/debug" value="false"/>

+<mapEntry key="org.eclipse.update.core/debug" value="true"/>

+<mapEntry key="org.eclipse.update.core/debug/configuration" value="false"/>

+<mapEntry key="org.eclipse.update.core/debug/install" value="false"/>

+<mapEntry key="org.eclipse.update.core/debug/installhandler" value="false"/>

+<mapEntry key="org.eclipse.update.core/debug/parsing" value="false"/>

+<mapEntry key="org.eclipse.update.core/debug/reconciler" value="false"/>

+<mapEntry key="org.eclipse.update.core/debug/type" value="false"/>

+<mapEntry key="org.eclipse.update.core/debug/warning" value="false"/>

+<mapEntry key="org.eclipse.update.core/debug/web" value="false"/>

+</mapAttribute>

+<booleanAttribute key="useCustomFeatures" value="false"/>

+<booleanAttribute key="useDefaultConfig" value="true"/>

+<booleanAttribute key="useDefaultConfigArea" value="true"/>

+<booleanAttribute key="useNamedJRE" value="true"/>

+<booleanAttribute key="useProduct" value="false"/>

+<booleanAttribute key="usefeatures" value="false"/>

+</launchConfiguration>

diff --git a/org.eclipse.emf.cdo.server/META-INF/MANIFEST.MF b/org.eclipse.emf.cdo.server/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..b35cecd
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/META-INF/MANIFEST.MF
@@ -0,0 +1,29 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: org.eclipse.emf.cdo.server;singleton:=true
+Bundle-Version: 4.1.0.qualifier
+Bundle-Name: %pluginName
+Bundle-Vendor: %providerName
+Bundle-Localization: plugin
+Bundle-ActivationPolicy: lazy
+Bundle-Activator: org.eclipse.emf.cdo.internal.server.bundle.OM$Activator
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
+Bundle-ClassPath: .
+Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.4.0,4.0.0)";resolution:=optional,
+ org.eclipse.emf.cdo;bundle-version="[4.0.0,5.0.0)";visibility:=reexport,
+ org.eclipse.net4j.util;bundle-version="[3.1.0,4.0.0)";visibility:=reexport
+Export-Package: org.eclipse.emf.cdo.internal.server;version="4.1.0";
+  x-friends:="org.eclipse.emf.cdo.server.db,
+   org.eclipse.emf.cdo.server.net4j,
+   org.eclipse.emf.cdo.tests,
+   org.eclipse.emf.cdo.workspace,
+   org.eclipse.emf.cdo.server.hibernate",
+ org.eclipse.emf.cdo.internal.server.bundle;version="4.1.0";x-internal:=true,
+ org.eclipse.emf.cdo.internal.server.embedded;version="4.1.0";x-friends:="org.eclipse.emf.cdo.tests",
+ org.eclipse.emf.cdo.internal.server.mem;version="4.1.0";x-friends:="org.eclipse.emf.cdo.tests",
+ org.eclipse.emf.cdo.internal.server.messages;version="4.1.0";x-internal:=true,
+ org.eclipse.emf.cdo.internal.server.syncing;version="4.1.0";x-friends:="org.eclipse.emf.cdo.tests",
+ org.eclipse.emf.cdo.server;version="4.1.0",
+ org.eclipse.emf.cdo.server.embedded;version="4.1.0",
+ org.eclipse.emf.cdo.server.mem;version="4.1.0",
+ org.eclipse.emf.cdo.spi.server;version="4.1.0"
diff --git a/org.eclipse.emf.cdo.server/about.html b/org.eclipse.emf.cdo.server/about.html
new file mode 100644
index 0000000..d35d5ae
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/about.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+ 
+<p>June 5, 2007</p>	
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;).  Unless otherwise 
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;).  A copy of the EPL is available 
+at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is 
+being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content.  Check the Redistributor's license that was 
+provided with the Content.  If no such license exists, contact the Redistributor.  Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
+
+</body>
+</html>
diff --git a/org.eclipse.emf.cdo.server/about.ini b/org.eclipse.emf.cdo.server/about.ini
new file mode 100644
index 0000000..b7e87ca
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/about.ini
@@ -0,0 +1,15 @@
+# about.ini
+# contains information about a feature
+# java.io.Properties file (ISO 8859-1 with "\" escapes)
+# "%key" are externalized strings defined in about.properties
+# This file does not need to be translated.
+
+# Property "aboutText" contains blurb for "About" dialog (translated)
+aboutText=%featureText
+
+# Property "featureImage" contains path to feature image (32x32)
+featureImage=modeling32.png
+
+# Property "appName" contains name of the application (translated)
+appName=%featureName
+
diff --git a/org.eclipse.emf.cdo.server/about.mappings b/org.eclipse.emf.cdo.server/about.mappings
new file mode 100644
index 0000000..bddaab4
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/about.mappings
@@ -0,0 +1,6 @@
+# about.mappings
+# contains fill-ins for about.properties
+# java.io.Properties file (ISO 8859-1 with "\" escapes)
+# This file does not need to be translated.
+
+0=@build@
\ No newline at end of file
diff --git a/org.eclipse.emf.cdo.server/about.properties b/org.eclipse.emf.cdo.server/about.properties
new file mode 100644
index 0000000..24af1ff
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/about.properties
@@ -0,0 +1,31 @@
+# Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+# 
+# Contributors:
+#    Eike Stepper - initial API and implementation
+   
+# NLS_MESSAGEFORMAT_VAR
+
+# ==============================================================================
+# Do not change the properties between this line and the last line containing:
+# %%% END OF TRANSLATED PROPERTIES %%%
+# Instead, either redefine an existing property, or create a new property,
+# append it to the end of the file, and change the code to use the new name.
+# ==============================================================================
+
+featureName = CDO Model Repository Server
+featureText = CDO Model Repository Server\n\
+Version: {featureVersion}\n\
+Build id: {0}\n\
+\n\
+Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others. All rights reserved.\n\
+\n\
+Visit http://www.eclipse.org/cdo
+
+# ==============================================================================
+# %%% END OF TRANSLATED PROPERTIES %%%
+# The above properties have been shipped for translation.
+# ==============================================================================
diff --git a/org.eclipse.emf.cdo.server/build.properties b/org.eclipse.emf.cdo.server/build.properties
new file mode 100644
index 0000000..2c3acd3
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/build.properties
@@ -0,0 +1,32 @@
+# Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#    Eike Stepper - initial API and implementation
+
+# NLS_MESSAGEFORMAT_VAR
+
+bin.includes = .,\
+               META-INF/,\
+               plugin.properties,\
+               .options,\
+               about.html,\
+               copyright.txt,\
+               plugin.xml,\
+               schema/,\
+               about.ini,\
+               about.mappings,\
+               about.properties,\
+               modeling32.png
+jars.compile.order = .
+source.. = src/
+output.. = bin/
+src.includes = about.html,\
+               copyright.txt,\
+               CDOServer.launch,\
+               CDOServer_SSL.launch
+
+org.eclipse.emf.cdo.releng.javadoc.project = org.eclipse.emf.cdo.doc
diff --git a/org.eclipse.emf.cdo.server/copyright.txt b/org.eclipse.emf.cdo.server/copyright.txt
new file mode 100644
index 0000000..e921242
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/copyright.txt
@@ -0,0 +1,8 @@
+Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+All rights reserved. This program and the accompanying materials
+are made available under the terms of the Eclipse Public License v1.0
+which accompanies this distribution, and is available at
+http://www.eclipse.org/legal/epl-v10.html
+
+Contributors:
+   Eike Stepper - initial API and implementation
\ No newline at end of file
diff --git a/org.eclipse.emf.cdo.server/modeling32.png b/org.eclipse.emf.cdo.server/modeling32.png
new file mode 100644
index 0000000..6b08de2
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/modeling32.png
Binary files differ
diff --git a/org.eclipse.emf.cdo.server/plugin.properties b/org.eclipse.emf.cdo.server/plugin.properties
new file mode 100644
index 0000000..9cc5cf8
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/plugin.properties
@@ -0,0 +1,17 @@
+# Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#    Eike Stepper - initial API and implementation
+
+pluginName = CDO Model Repository Server
+providerName = Eclipse Modeling Project
+
+app.name = CDOServer
+
+extension-point.name = CDO Store Factories
+extension-point.name.0 = CDO Repository Factories
+extension-point.name.1 = CDO Application Extensions
diff --git a/org.eclipse.emf.cdo.server/plugin.xml b/org.eclipse.emf.cdo.server/plugin.xml
new file mode 100644
index 0000000..124577b
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/plugin.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<!--
+	Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+	All rights reserved. This program and the accompanying materials
+	are made available under the terms of the Eclipse Public License v1.0
+	which accompanies this distribution, and is available at
+	http://www.eclipse.org/legal/epl-v10.html
+
+	Contributors:
+	  Eike Stepper - initial API and implementation
+-->
+
+<plugin>
+
+   	<extension-point id="storeFactories" name="%extension-point.name" schema="schema/storeFactories.exsd"/>
+   	<extension-point id="repositoryFactories" name="%extension-point.name.0" schema="schema/repositoryFactories.exsd"/>
+   	<extension-point id="appExtensions" name="%extension-point.name.1" schema="schema/appExtensions.exsd"/>
+
+		<extension point="org.eclipse.net4j.util.factories">
+      	<factory
+            productGroup="org.eclipse.net4j.Negotiators"
+            type="challenge"
+            class="org.eclipse.net4j.util.security.ChallengeNegotiatorFactory"/>
+      	<factory
+            productGroup="org.eclipse.emf.cdo.server.browsers"
+            type="default"
+            class="org.eclipse.emf.cdo.server.CDOServerBrowser$ContainerBased$Factory"/>
+   	</extension>
+
+		<extension point="org.eclipse.net4j.util.elementProcessors">
+				<elementProcessor class="org.eclipse.net4j.util.security.ChallengeNegotiatorConfigurer"/>
+				<elementProcessor class="org.eclipse.emf.cdo.spi.server.RepositoryUserManager$RepositoryInjector"/>
+  	</extension>
+
+  	<extension point="org.eclipse.emf.cdo.server.repositoryFactories">
+      	<repositoryFactory
+        	class="org.eclipse.emf.cdo.spi.server.RepositoryFactory"
+          repositoryType="default"/>
+		</extension>
+
+  	<extension point="org.eclipse.emf.cdo.server.storeFactories">
+      	<storeFactory
+        	class="org.eclipse.emf.cdo.internal.server.mem.MEMStoreFactory"
+          storeType="mem"/>
+   	</extension>
+
+    <extension id="app" point="org.eclipse.core.runtime.applications" name="%app.name">
+				<application cardinality="1" thread="any">
+					<run class="org.eclipse.emf.cdo.internal.server.bundle.CDOServerApplication"/>
+ 				</application>
+		</extension>
+
+</plugin>
diff --git a/org.eclipse.emf.cdo.server/schema/appExtensions.exsd b/org.eclipse.emf.cdo.server/schema/appExtensions.exsd
new file mode 100644
index 0000000..3b3f70e
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/schema/appExtensions.exsd
@@ -0,0 +1,103 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.emf.cdo.server" xmlns="http://www.w3.org/2001/XMLSchema">
+<annotation>
+      <appInfo>
+         <meta.schema plugin="org.eclipse.emf.cdo.server" id="appExtensions" name="Application Extensions"/>
+      </appInfo>
+      <documentation>
+         [Enter description of this extension point.]
+      </documentation>
+   </annotation>
+
+   <element name="extension">
+      <annotation>
+         <appInfo>
+            <meta.element />
+         </appInfo>
+      </annotation>
+      <complexType>
+         <sequence>
+            <element ref="appExtension" minOccurs="1" maxOccurs="unbounded"/>
+         </sequence>
+         <attribute name="point" type="string" use="required">
+            <annotation>
+               <documentation>
+
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="name" type="string">
+            <annotation>
+               <documentation>
+
+               </documentation>
+               <appInfo>
+                  <meta.attribute translatable="true"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="appExtension">
+      <complexType>
+         <attribute name="class" type="string" use="required">
+            <annotation>
+               <documentation>
+
+               </documentation>
+               <appInfo>
+                  <meta.attribute kind="java" basedOn=":org.eclipse.emf.cdo.spi.server.IAppExtension"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="since"/>
+      </appInfo>
+      <documentation>
+         [Enter the first release in which this extension point appears.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="examples"/>
+      </appInfo>
+      <documentation>
+         [Enter extension point usage example here.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="apiinfo"/>
+      </appInfo>
+      <documentation>
+         [Enter API information here.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appinfo>
+         <meta.section type="copyright"/>
+      </appinfo>
+      <documentation>
+         Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.&lt;br&gt;
+All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at &lt;a href=&quot;http://www.eclipse.org/legal/epl-v10.html&quot;&gt;http://www.eclipse.org/legal/epl-v10.html&lt;/a&gt;
+      </documentation>
+   </annotation>
+
+
+</schema>
diff --git a/org.eclipse.emf.cdo.server/schema/repositoryFactories.exsd b/org.eclipse.emf.cdo.server/schema/repositoryFactories.exsd
new file mode 100644
index 0000000..1cdabf2
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/schema/repositoryFactories.exsd
@@ -0,0 +1,113 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.emf.cdo.server">
+<annotation>
+      <appInfo>
+         <meta.schema plugin="org.eclipse.emf.cdo.server" id="repositoryFactories" name="CDO Repository Factories"/>
+      </appInfo>
+      <documentation>
+         [Enter description of this extension point.]
+      </documentation>
+   </annotation>
+
+   <element name="extension">
+      <complexType>
+         <sequence>
+            <element ref="repositoryFactory" minOccurs="1" maxOccurs="unbounded"/>
+         </sequence>
+         <attribute name="point" type="string" use="required">
+            <annotation>
+               <documentation>
+
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="name" type="string">
+            <annotation>
+               <documentation>
+
+               </documentation>
+               <appInfo>
+                  <meta.attribute translatable="true"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="repositoryFactory">
+      <complexType>
+         <attribute name="repositoryType" type="string" use="required">
+            <annotation>
+               <documentation>
+
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="class" type="string" use="required">
+            <annotation>
+               <documentation>
+
+               </documentation>
+               <appInfo>
+                  <meta.attribute kind="java" basedOn=":org.eclipse.emf.cdo.server.IRepositoryFactory"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="since"/>
+      </appInfo>
+      <documentation>
+         [Enter the first release in which this extension point appears.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="examples"/>
+      </appInfo>
+      <documentation>
+         [Enter extension point usage example here.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="apiInfo"/>
+      </appInfo>
+      <documentation>
+         [Enter API information here.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="implementation"/>
+      </appInfo>
+      <documentation>
+         [Enter information about supplied implementation of this extension point.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appinfo>
+         <meta.section type="copyright"/>
+      </appinfo>
+      <documentation>
+         Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.&lt;br&gt;
+All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at &lt;a href=&quot;http://www.eclipse.org/legal/epl-v10.html&quot;&gt;http://www.eclipse.org/legal/epl-v10.html&lt;/a&gt;
+      </documentation>
+   </annotation>
+
+</schema>
diff --git a/org.eclipse.emf.cdo.server/schema/storeFactories.exsd b/org.eclipse.emf.cdo.server/schema/storeFactories.exsd
new file mode 100644
index 0000000..b6cd6bd
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/schema/storeFactories.exsd
@@ -0,0 +1,113 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.emf.cdo.server">
+<annotation>
+      <appInfo>
+         <meta.schema plugin="org.eclipse.emf.cdo.server" id="storeFactories" name="CDO Store Factories"/>
+      </appInfo>
+      <documentation>
+         [Enter description of this extension point.]
+      </documentation>
+   </annotation>
+
+   <element name="extension">
+      <complexType>
+         <sequence>
+            <element ref="storeFactory" minOccurs="1" maxOccurs="unbounded"/>
+         </sequence>
+         <attribute name="point" type="string" use="required">
+            <annotation>
+               <documentation>
+
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="name" type="string">
+            <annotation>
+               <documentation>
+
+               </documentation>
+               <appInfo>
+                  <meta.attribute translatable="true"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="storeFactory">
+      <complexType>
+         <attribute name="storeType" type="string" use="required">
+            <annotation>
+               <documentation>
+
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="class" type="string" use="required">
+            <annotation>
+               <documentation>
+
+               </documentation>
+               <appInfo>
+                  <meta.attribute kind="java" basedOn=":org.eclipse.emf.cdo.server.IStoreFactory"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="since"/>
+      </appInfo>
+      <documentation>
+         [Enter the first release in which this extension point appears.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="examples"/>
+      </appInfo>
+      <documentation>
+         [Enter extension point usage example here.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="apiInfo"/>
+      </appInfo>
+      <documentation>
+         [Enter API information here.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="implementation"/>
+      </appInfo>
+      <documentation>
+         [Enter information about supplied implementation of this extension point.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appinfo>
+         <meta.section type="copyright"/>
+      </appinfo>
+      <documentation>
+         Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.&lt;br&gt;
+All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at &lt;a href=&quot;http://www.eclipse.org/legal/epl-v10.html&quot;&gt;http://www.eclipse.org/legal/epl-v10.html&lt;/a&gt;
+      </documentation>
+   </annotation>
+
+</schema>
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/CommitManager.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/CommitManager.java
new file mode 100644
index 0000000..9a0d759
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/CommitManager.java
@@ -0,0 +1,191 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Simon McDuff - initial API and implementation
+ *    Eike Stepper - maintenance
+ */
+package org.eclipse.emf.cdo.internal.server;
+
+import org.eclipse.emf.cdo.spi.server.InternalCommitContext;
+import org.eclipse.emf.cdo.spi.server.InternalCommitManager;
+import org.eclipse.emf.cdo.spi.server.InternalRepository;
+import org.eclipse.emf.cdo.spi.server.InternalTransaction;
+
+import org.eclipse.net4j.util.ReflectUtil.ExcludeFromDump;
+import org.eclipse.net4j.util.lifecycle.Lifecycle;
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+/**
+ * @author Simon McDuff
+ * @since 2.0
+ */
+public class CommitManager extends Lifecycle implements InternalCommitManager
+{
+  private InternalRepository repository;
+
+  @ExcludeFromDump
+  private transient ExecutorService executors;
+
+  private boolean shutdownExecutorService;
+
+  @ExcludeFromDump
+  private transient Map<InternalTransaction, TransactionCommitContextEntry> contextEntries = new ConcurrentHashMap<InternalTransaction, TransactionCommitContextEntry>();
+
+  public CommitManager()
+  {
+  }
+
+  public InternalRepository getRepository()
+  {
+    return repository;
+  }
+
+  public void setRepository(InternalRepository repository)
+  {
+    this.repository = repository;
+  }
+
+  public synchronized ExecutorService getExecutors()
+  {
+    if (executors == null)
+    {
+      shutdownExecutorService = true;
+      executors = Executors.newFixedThreadPool(10);
+    }
+
+    return executors;
+  }
+
+  public synchronized void setExecutors(ExecutorService executors)
+  {
+    if (shutdownExecutorService)
+    {
+      this.executors.shutdown();
+      shutdownExecutorService = false;
+    }
+
+    this.executors = executors;
+  }
+
+  @Override
+  protected void doDeactivate() throws Exception
+  {
+    super.doDeactivate();
+    setExecutors(null);
+  }
+
+  /**
+   * Create a future to execute commitContext in a different thread.
+   */
+  public void preCommit(InternalCommitContext commitContext, OMMonitor monitor)
+  {
+    TransactionCommitContextEntry contextEntry = new TransactionCommitContextEntry(monitor);
+    contextEntry.setContext(commitContext);
+
+    Future<Object> future = getExecutors().submit(contextEntry.createCallable());
+    contextEntry.setFuture(future);
+
+    contextEntries.put(commitContext.getTransaction(), contextEntry);
+  }
+
+  /**
+   * Called after a commitContext is done successfully or not.
+   */
+  public void remove(InternalCommitContext commitContext)
+  {
+    contextEntries.remove(commitContext.getTransaction());
+  }
+
+  public void rollback(InternalCommitContext commitContext)
+  {
+    TransactionCommitContextEntry contextEntry = contextEntries.get(commitContext.getTransaction());
+    if (contextEntry != null)
+    {
+      contextEntry.getFuture().cancel(true);
+      commitContext.rollback("Remote rollback"); //$NON-NLS-1$
+      commitContext.postCommit(false);
+    }
+  }
+
+  /**
+   * Waiting for a commit to be done.
+   */
+  public void waitForTermination(InternalTransaction transaction) throws InterruptedException, ExecutionException
+  {
+    TransactionCommitContextEntry contextEntry = contextEntries.get(transaction);
+    contextEntry.getFuture().get();
+  }
+
+  public InternalCommitContext get(InternalTransaction transaction)
+  {
+    TransactionCommitContextEntry contextEntry = contextEntries.get(transaction);
+    if (contextEntry != null)
+    {
+      return contextEntry.getContext();
+    }
+
+    return null;
+  }
+
+  /**
+   * @author Simon McDuff
+   */
+  private static final class TransactionCommitContextEntry
+  {
+    private InternalCommitContext context;
+
+    private Future<Object> future;
+
+    private OMMonitor monitor;
+
+    public TransactionCommitContextEntry(OMMonitor monitor)
+    {
+      this.monitor = monitor;
+    }
+
+    public Callable<Object> createCallable()
+    {
+      return new Callable<Object>()
+      {
+        public Object call() throws Exception
+        {
+          context.write(monitor);
+          return null;
+        }
+      };
+    }
+
+    public InternalCommitContext getContext()
+    {
+      return context;
+    }
+
+    public void setContext(InternalCommitContext context)
+    {
+      this.context = context;
+    }
+
+    public Future<Object> getFuture()
+    {
+      return future;
+    }
+
+    public void setFuture(Future<Object> future)
+    {
+      this.future = future;
+    }
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/DelegatingCommitContext.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/DelegatingCommitContext.java
new file mode 100644
index 0000000..f724419
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/DelegatingCommitContext.java
@@ -0,0 +1,109 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.internal.server;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.server.IStoreAccessor;
+import org.eclipse.emf.cdo.server.IStoreAccessor.CommitContext;
+import org.eclipse.emf.cdo.server.ITransaction;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionDelta;
+
+import org.eclipse.emf.ecore.EClass;
+
+import java.util.Map;
+
+/**
+ * @author Eike Stepper
+ */
+public abstract class DelegatingCommitContext implements IStoreAccessor.CommitContext
+{
+  protected abstract CommitContext getDelegate();
+
+  public ITransaction getTransaction()
+  {
+    return getDelegate().getTransaction();
+  }
+
+  public CDOBranchPoint getBranchPoint()
+  {
+    return getDelegate().getBranchPoint();
+  }
+
+  public String getUserID()
+  {
+    return getDelegate().getUserID();
+  }
+
+  public String getCommitComment()
+  {
+    return getDelegate().getCommitComment();
+  }
+
+  public boolean isAutoReleaseLocksEnabled()
+  {
+    return getDelegate().isAutoReleaseLocksEnabled();
+  }
+
+  public InternalCDOPackageRegistry getPackageRegistry()
+  {
+    return getDelegate().getPackageRegistry();
+  }
+
+  public InternalCDOPackageUnit[] getNewPackageUnits()
+  {
+    return getDelegate().getNewPackageUnits();
+  }
+
+  public InternalCDORevision[] getNewObjects()
+  {
+    return getDelegate().getNewObjects();
+  }
+
+  public InternalCDORevision[] getDirtyObjects()
+  {
+    return getDelegate().getDirtyObjects();
+  }
+
+  public InternalCDORevisionDelta[] getDirtyObjectDeltas()
+  {
+    return getDelegate().getDirtyObjectDeltas();
+  }
+
+  public CDOID[] getDetachedObjects()
+  {
+    return getDelegate().getDetachedObjects();
+  }
+
+  public Map<CDOID, EClass> getDetachedObjectTypes()
+  {
+    return getDelegate().getDetachedObjectTypes();
+  }
+
+  public CDORevision getRevision(CDOID id)
+  {
+    return getDelegate().getRevision(id);
+  }
+
+  public Map<CDOID, CDOID> getIDMappings()
+  {
+    return getDelegate().getIDMappings();
+  }
+
+  public String getRollbackMessage()
+  {
+    return getDelegate().getRollbackMessage();
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/DelegatingRepository.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/DelegatingRepository.java
new file mode 100644
index 0000000..8c4fd91
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/DelegatingRepository.java
@@ -0,0 +1,286 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.internal.server;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.branch.CDOBranchVersion;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.model.CDOPackageUnit;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.util.CDOQueryInfo;
+import org.eclipse.emf.cdo.server.IQueryHandler;
+import org.eclipse.emf.cdo.server.IQueryHandlerProvider;
+import org.eclipse.emf.cdo.server.IStoreAccessor;
+import org.eclipse.emf.cdo.server.IStoreAccessor.CommitContext;
+import org.eclipse.emf.cdo.server.ITransaction;
+import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranchManager;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager;
+import org.eclipse.emf.cdo.spi.common.revision.RevisionInfo;
+import org.eclipse.emf.cdo.spi.server.InternalCommitManager;
+import org.eclipse.emf.cdo.spi.server.InternalLockManager;
+import org.eclipse.emf.cdo.spi.server.InternalQueryManager;
+import org.eclipse.emf.cdo.spi.server.InternalRepository;
+import org.eclipse.emf.cdo.spi.server.InternalSession;
+import org.eclipse.emf.cdo.spi.server.InternalSessionManager;
+import org.eclipse.emf.cdo.spi.server.InternalStore;
+
+import org.eclipse.net4j.util.collection.Pair;
+import org.eclipse.net4j.util.event.IListener;
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Eike Stepper
+ */
+public abstract class DelegatingRepository implements InternalRepository
+{
+  public DelegatingRepository()
+  {
+  }
+
+  protected abstract InternalRepository getDelegate();
+
+  public void addHandler(Handler handler)
+  {
+    getDelegate().addHandler(handler);
+  }
+
+  public void addListener(IListener listener)
+  {
+    getDelegate().addListener(listener);
+  }
+
+  public long[] createCommitTimeStamp(OMMonitor monitor)
+  {
+    return getDelegate().createCommitTimeStamp(monitor);
+  }
+
+  public IStoreAccessor ensureChunk(InternalCDORevision revision, EStructuralFeature feature, int chunkStart,
+      int chunkEnd)
+  {
+    return getDelegate().ensureChunk(revision, feature, chunkStart, chunkEnd);
+  }
+
+  public InternalCommitManager getCommitManager()
+  {
+    return getDelegate().getCommitManager();
+  }
+
+  public long getCreationTime()
+  {
+    return getDelegate().getCreationTime();
+  }
+
+  public Object[] getElements()
+  {
+    return getDelegate().getElements();
+  }
+
+  public long getLastCommitTimeStamp()
+  {
+    return getDelegate().getLastCommitTimeStamp();
+  }
+
+  public IListener[] getListeners()
+  {
+    return getDelegate().getListeners();
+  }
+
+  public InternalLockManager getLockManager()
+  {
+    return getDelegate().getLockManager();
+  }
+
+  public String getName()
+  {
+    return getDelegate().getName();
+  }
+
+  public InternalCDOPackageRegistry getPackageRegistry()
+  {
+    return getDelegate().getPackageRegistry();
+  }
+
+  public InternalCDOPackageRegistry getPackageRegistry(boolean considerCommitContext)
+  {
+    return getDelegate().getPackageRegistry(considerCommitContext);
+  }
+
+  public Map<String, String> getProperties()
+  {
+    return getDelegate().getProperties();
+  }
+
+  public IQueryHandler getQueryHandler(CDOQueryInfo info)
+  {
+    return getDelegate().getQueryHandler(info);
+  }
+
+  public IQueryHandlerProvider getQueryHandlerProvider()
+  {
+    return getDelegate().getQueryHandlerProvider();
+  }
+
+  public InternalQueryManager getQueryManager()
+  {
+    return getDelegate().getQueryManager();
+  }
+
+  public InternalCDORevisionManager getRevisionManager()
+  {
+    return getDelegate().getRevisionManager();
+  }
+
+  public InternalSessionManager getSessionManager()
+  {
+    return getDelegate().getSessionManager();
+  }
+
+  public InternalStore getStore()
+  {
+    return getDelegate().getStore();
+  }
+
+  public String getUUID()
+  {
+    return getDelegate().getUUID();
+  }
+
+  public boolean hasListeners()
+  {
+    return getDelegate().hasListeners();
+  }
+
+  public boolean isEmpty()
+  {
+    return getDelegate().isEmpty();
+  }
+
+  public boolean isSupportingAudits()
+  {
+    return getDelegate().isSupportingAudits();
+  }
+
+  public boolean isSupportingBranches()
+  {
+    return getDelegate().isSupportingBranches();
+  }
+
+  public EPackage[] loadPackages(CDOPackageUnit packageUnit)
+  {
+    return getDelegate().loadPackages(packageUnit);
+  }
+
+  public InternalCDOBranchManager getBranchManager()
+  {
+    return getDelegate().getBranchManager();
+  }
+
+  public void setBranchManager(InternalCDOBranchManager branchManager)
+  {
+    getDelegate().setBranchManager(branchManager);
+  }
+
+  public Pair<Integer, Long> createBranch(int branchID, BranchInfo branchInfo)
+  {
+    return getDelegate().createBranch(branchID, branchInfo);
+  }
+
+  public BranchInfo loadBranch(int branchID)
+  {
+    return getDelegate().loadBranch(branchID);
+  }
+
+  public SubBranchInfo[] loadSubBranches(int branchID)
+  {
+    return getDelegate().loadSubBranches(branchID);
+  }
+
+  public List<InternalCDORevision> loadRevisions(List<RevisionInfo> infos, CDOBranchPoint branchPoint,
+      int referenceChunk, int prefetchDepth)
+  {
+    return getDelegate().loadRevisions(infos, branchPoint, referenceChunk, prefetchDepth);
+  }
+
+  public InternalCDORevision loadRevisionByVersion(CDOID id, CDOBranchVersion branchVersion, int referenceChunk)
+  {
+    return getDelegate().loadRevisionByVersion(id, branchVersion, referenceChunk);
+  }
+
+  public void notifyReadAccessHandlers(InternalSession session, CDORevision[] revisions,
+      List<CDORevision> additionalRevisions)
+  {
+    getDelegate().notifyReadAccessHandlers(session, revisions, additionalRevisions);
+  }
+
+  public void notifyWriteAccessHandlers(ITransaction transaction, CommitContext commitContext, boolean beforeCommit,
+      OMMonitor monitor)
+  {
+    getDelegate().notifyWriteAccessHandlers(transaction, commitContext, beforeCommit, monitor);
+  }
+
+  public void removeHandler(Handler handler)
+  {
+    getDelegate().removeHandler(handler);
+  }
+
+  public void removeListener(IListener listener)
+  {
+    getDelegate().removeListener(listener);
+  }
+
+  public void setName(String name)
+  {
+    getDelegate().setName(name);
+  }
+
+  public void setProperties(Map<String, String> properties)
+  {
+    getDelegate().setProperties(properties);
+  }
+
+  public void setQueryHandlerProvider(IQueryHandlerProvider queryHandlerProvider)
+  {
+    getDelegate().setQueryHandlerProvider(queryHandlerProvider);
+  }
+
+  public void setRevisionManager(InternalCDORevisionManager revisionManager)
+  {
+    getDelegate().setRevisionManager(revisionManager);
+  }
+
+  public void setSessionManager(InternalSessionManager sessionManager)
+  {
+    getDelegate().setSessionManager(sessionManager);
+  }
+
+  public void setStore(InternalStore store)
+  {
+    getDelegate().setStore(store);
+  }
+
+  public long getTimeStamp()
+  {
+    return getDelegate().getTimeStamp();
+  }
+
+  public void validateTimeStamp(long timeStamp) throws IllegalArgumentException
+  {
+    getDelegate().validateTimeStamp(timeStamp);
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/LockManager.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/LockManager.java
new file mode 100644
index 0000000..5db93a4
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/LockManager.java
@@ -0,0 +1,694 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Simon McDuff - initial API and implementation
+ *    Eike Stepper - maintenance
+ *    Caspar De Groot - write options
+ */
+package org.eclipse.emf.cdo.internal.server;
+
+import org.eclipse.emf.cdo.common.CDOCommonView;
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.id.CDOIDUtil;
+import org.eclipse.emf.cdo.common.revision.CDOIDAndBranch;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.server.IRepository;
+import org.eclipse.emf.cdo.server.ISession;
+import org.eclipse.emf.cdo.server.ISessionManager;
+import org.eclipse.emf.cdo.server.IStoreAccessor;
+import org.eclipse.emf.cdo.server.IStoreAccessor.DurableLocking;
+import org.eclipse.emf.cdo.server.IStoreAccessor.DurableLocking2;
+import org.eclipse.emf.cdo.server.IView;
+import org.eclipse.emf.cdo.server.StoreThreadLocal;
+import org.eclipse.emf.cdo.spi.common.branch.CDOBranchUtil;
+import org.eclipse.emf.cdo.spi.server.InternalLockManager;
+import org.eclipse.emf.cdo.spi.server.InternalRepository;
+import org.eclipse.emf.cdo.spi.server.InternalStore;
+import org.eclipse.emf.cdo.spi.server.InternalView;
+
+import org.eclipse.net4j.util.CheckUtil;
+import org.eclipse.net4j.util.ImplementationError;
+import org.eclipse.net4j.util.ReflectUtil.ExcludeFromDump;
+import org.eclipse.net4j.util.WrappedException;
+import org.eclipse.net4j.util.concurrent.RWOLockManager;
+import org.eclipse.net4j.util.container.ContainerEventAdapter;
+import org.eclipse.net4j.util.container.IContainer;
+import org.eclipse.net4j.util.event.IListener;
+import org.eclipse.net4j.util.lifecycle.ILifecycle;
+import org.eclipse.net4j.util.lifecycle.LifecycleEventAdapter;
+import org.eclipse.net4j.util.options.IOptionsContainer;
+
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+/**
+ * @author Simon McDuff
+ * @since 3.0
+ */
+public class LockManager extends RWOLockManager<Object, IView> implements InternalLockManager
+{
+  private InternalRepository repository;
+
+  private Map<String, InternalView> openViews = new HashMap<String, InternalView>();
+
+  private Map<String, DurableView> durableViews = new HashMap<String, DurableView>();
+
+  @ExcludeFromDump
+  private transient IListener sessionListener = new ContainerEventAdapter<IView>()
+  {
+    @Override
+    protected void onRemoved(IContainer<IView> container, IView view)
+    {
+      String durableLockingID = view.getDurableLockingID();
+      if (durableLockingID == null)
+      {
+        unlock(view);
+      }
+      else
+      {
+        changeContext(view, new DurableView(durableLockingID));
+        unregisterOpenView(durableLockingID);
+      }
+    }
+  };
+
+  @ExcludeFromDump
+  private transient IListener sessionManagerListener = new ContainerEventAdapter<ISession>()
+  {
+    @Override
+    protected void onAdded(IContainer<ISession> container, ISession session)
+    {
+      session.addListener(sessionListener);
+    }
+
+    @Override
+    protected void onRemoved(IContainer<ISession> container, ISession session)
+    {
+      session.removeListener(sessionListener);
+    }
+  };
+
+  public LockManager()
+  {
+  }
+
+  public InternalRepository getRepository()
+  {
+    return repository;
+  }
+
+  public void setRepository(InternalRepository repository)
+  {
+    this.repository = repository;
+  }
+
+  public synchronized Object getLockEntryObject(Object key)
+  {
+    LockState<Object, IView> lockState = getObjectToLocksMap().get(key);
+    return lockState == null ? null : lockState.getLockedObject();
+  }
+
+  public Object getLockKey(CDOID id, CDOBranch branch)
+  {
+    if (repository.isSupportingBranches())
+    {
+      return CDOIDUtil.createIDAndBranch(id, branch);
+    }
+
+    return id;
+  }
+
+  public synchronized Map<CDOID, LockGrade> getLocks(final IView view)
+  {
+    final Map<CDOID, LockGrade> result = new HashMap<CDOID, LockGrade>();
+
+    for (LockState<Object, IView> lockState : getObjectToLocksMap().values())
+    {
+      LockGrade grade = LockGrade.NONE;
+      if (lockState.hasLock(LockType.READ, view, false))
+      {
+        grade = grade.getUpdated(LockType.READ, true);
+      }
+
+      if (lockState.hasLock(LockType.WRITE, view, false))
+      {
+        grade = grade.getUpdated(LockType.WRITE, true);
+      }
+
+      if (lockState.hasLock(LockType.OPTION, view, false))
+      {
+        grade = grade.getUpdated(LockType.OPTION, true);
+      }
+
+      if (grade != LockGrade.NONE)
+      {
+        CDOID id = getLockKeyID(lockState.getLockedObject());
+        result.put(id, grade);
+      }
+    }
+
+    return result;
+  }
+
+  @Deprecated
+  public void lock(boolean explicit, LockType type, IView view, Collection<? extends Object> objectsToLock, long timeout)
+      throws InterruptedException
+  {
+    lock2(explicit, type, view, objectsToLock, timeout);
+  }
+
+  public List<LockState<Object, IView>> lock2(boolean explicit, LockType type, IView view,
+      Collection<? extends Object> objectsToLock, long timeout) throws InterruptedException
+  {
+    String durableLockingID = null;
+    DurableLocking accessor = null;
+
+    if (explicit)
+    {
+      durableLockingID = view.getDurableLockingID();
+      if (durableLockingID != null)
+      {
+        accessor = getDurableLocking();
+      }
+    }
+
+    List<LockState<Object, IView>> newLockStates = super.lock2(type, view, objectsToLock, timeout);
+
+    if (accessor != null)
+    {
+      accessor.lock(durableLockingID, type, objectsToLock);
+    }
+
+    return newLockStates;
+  }
+
+  @Deprecated
+  public synchronized void unlock(boolean explicit, LockType type, IView view,
+      Collection<? extends Object> objectsToUnlock)
+  {
+    unlock2(explicit, type, view, objectsToUnlock);
+  }
+
+  public synchronized List<LockState<Object, IView>> unlock2(boolean explicit, LockType type, IView view,
+      Collection<? extends Object> objectsToUnlock)
+  {
+    List<LockState<Object, IView>> newLockStates = super.unlock2(type, view, objectsToUnlock);
+
+    if (explicit)
+    {
+      String durableLockingID = view.getDurableLockingID();
+      if (durableLockingID != null)
+      {
+        DurableLocking accessor = getDurableLocking();
+        accessor.unlock(durableLockingID, type, objectsToUnlock);
+      }
+    }
+
+    return newLockStates;
+  }
+
+  @Deprecated
+  public synchronized void unlock(boolean explicit, IView view)
+  {
+    unlock(explicit, view);
+  }
+
+  public synchronized List<LockState<Object, IView>> unlock2(boolean explicit, IView view)
+  {
+    if (explicit)
+    {
+      String durableLockingID = view.getDurableLockingID();
+      if (durableLockingID != null)
+      {
+        DurableLocking accessor = getDurableLocking();
+        accessor.unlock(durableLockingID);
+      }
+    }
+
+    return super.unlock2(view);
+  }
+
+  public LockArea createLockArea(String userID, CDOBranchPoint branchPoint, boolean readOnly,
+      Map<CDOID, LockGrade> locks)
+  {
+    return createLockArea(userID, branchPoint, readOnly, locks, null);
+  }
+
+  private LockArea createLockArea(String userID, CDOBranchPoint branchPoint, boolean readOnly,
+      Map<CDOID, LockGrade> locks, String lockAreaID)
+  {
+    if (lockAreaID == null)
+    {
+      DurableLocking accessor = getDurableLocking();
+      return accessor.createLockArea(userID, branchPoint, readOnly, locks);
+    }
+
+    DurableLocking2 accessor = getDurableLocking2();
+    return accessor.createLockArea(lockAreaID, userID, branchPoint, readOnly, locks);
+  }
+
+  public LockArea createLockArea(InternalView view)
+  {
+    return createLockArea(view, null);
+  }
+
+  public LockArea createLockArea(InternalView view, String lockAreaID)
+  {
+    String userID = view.getSession().getUserID();
+    CDOBranchPoint branchPoint = CDOBranchUtil.copyBranchPoint(view);
+    boolean readOnly = view.isReadOnly();
+    Map<CDOID, LockGrade> locks = getLocks(view);
+
+    LockArea area = createLockArea(userID, branchPoint, readOnly, locks, lockAreaID);
+    synchronized (openViews)
+    {
+      openViews.put(area.getDurableLockingID(), view);
+    }
+
+    return area;
+  }
+
+  public LockArea getLockArea(String durableLockingID) throws LockAreaNotFoundException
+  {
+    DurableLocking accessor = getDurableLocking();
+    return accessor.getLockArea(durableLockingID);
+  }
+
+  public void getLockAreas(String userIDPrefix, LockArea.Handler handler)
+  {
+    if (userIDPrefix == null)
+    {
+      userIDPrefix = "";
+    }
+
+    DurableLocking accessor = getDurableLocking();
+    accessor.getLockAreas(userIDPrefix, handler);
+  }
+
+  public void deleteLockArea(String durableLockingID)
+  {
+    DurableLocking accessor = getDurableLocking();
+    accessor.deleteLockArea(durableLockingID);
+    unregisterOpenView(durableLockingID);
+  }
+
+  public IView openView(ISession session, int viewID, boolean readOnly, final String durableLockingID)
+  {
+    synchronized (openViews)
+    {
+      InternalView view = openViews.get(durableLockingID);
+      if (view != null)
+      {
+        throw new IllegalStateException("Durable view is already open: " + view);
+      }
+
+      LockArea area = getLockArea(durableLockingID);
+      if (area.isReadOnly() != readOnly)
+      {
+        throw new IllegalStateException("Durable read-only state does not match the request");
+      }
+
+      if (readOnly)
+      {
+        view = (InternalView)session.openView(viewID, area);
+      }
+      else
+      {
+        view = (InternalView)session.openTransaction(viewID, area);
+      }
+
+      changeContext(new DurableView(durableLockingID), view);
+      view.setDurableLockingID(durableLockingID);
+      view.addListener(new LifecycleEventAdapter()
+      {
+        @Override
+        protected void onDeactivated(ILifecycle lifecycle)
+        {
+          synchronized (openViews)
+          {
+            openViews.remove(durableLockingID);
+          }
+        }
+      });
+
+      openViews.put(durableLockingID, view);
+      return view;
+    }
+  }
+
+  @Override
+  protected void doActivate() throws Exception
+  {
+    super.doActivate();
+    loadDurableLocks();
+    getRepository().getSessionManager().addListener(sessionManagerListener);
+  }
+
+  @Override
+  protected void doDeactivate() throws Exception
+  {
+    ISessionManager sessionManager = getRepository().getSessionManager();
+    sessionManager.removeListener(sessionManagerListener);
+    for (ISession session : sessionManager.getSessions())
+    {
+      session.removeListener(sessionListener);
+    }
+
+    super.doDeactivate();
+  }
+
+  private DurableLocking getDurableLocking()
+  {
+    IStoreAccessor accessor = StoreThreadLocal.getAccessor();
+    if (accessor instanceof DurableLocking)
+    {
+      return (DurableLocking)accessor;
+    }
+
+    throw new IllegalStateException("Store does not implement " + DurableLocking.class.getSimpleName());
+  }
+
+  private DurableLocking2 getDurableLocking2()
+  {
+    IStoreAccessor accessor = StoreThreadLocal.getAccessor();
+    if (accessor instanceof DurableLocking2)
+    {
+      return (DurableLocking2)accessor;
+    }
+
+    throw new IllegalStateException("Store does not implement " + DurableLocking2.class.getSimpleName());
+  }
+
+  private void loadDurableLocks()
+  {
+    InternalStore store = repository.getStore();
+    IStoreAccessor reader = null;
+
+    try
+    {
+      reader = store.getReader(null);
+      if (reader instanceof DurableLocking)
+      {
+        StoreThreadLocal.setAccessor(reader);
+
+        DurableLockLoader handler = new DurableLockLoader();
+        getLockAreas(null, handler);
+      }
+    }
+    finally
+    {
+      StoreThreadLocal.release();
+    }
+  }
+
+  private void unregisterOpenView(String durableLockingID)
+  {
+    synchronized (openViews)
+    {
+      InternalView view = openViews.remove(durableLockingID);
+      if (view != null)
+      {
+        view.setDurableLockingID(null);
+      }
+    }
+  }
+
+  public CDOID getLockKeyID(Object key)
+  {
+    if (key instanceof CDOID)
+    {
+      return (CDOID)key;
+    }
+
+    if (key instanceof CDOIDAndBranch)
+    {
+      return ((CDOIDAndBranch)key).getID();
+    }
+
+    throw new ImplementationError("Unexpected lock object: " + key);
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  private final class DurableView implements IView, CDOCommonView.Options
+  {
+    private String durableLockingID;
+
+    public DurableView(String durableLockingID)
+    {
+      this.durableLockingID = durableLockingID;
+    }
+
+    public String getDurableLockingID()
+    {
+      return durableLockingID;
+    }
+
+    public int getViewID()
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public boolean isReadOnly()
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public CDOBranch getBranch()
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public long getTimeStamp()
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public CDORevision getRevision(CDOID id)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public void close()
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public boolean isClosed()
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public IRepository getRepository()
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public ISession getSession()
+    {
+      return null;
+    }
+
+    @Override
+    public int hashCode()
+    {
+      return durableLockingID.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj)
+    {
+      if (obj == this)
+      {
+        return true;
+      }
+
+      if (obj instanceof DurableView)
+      {
+        DurableView that = (DurableView)obj;
+        return durableLockingID.equals(that.getDurableLockingID());
+      }
+
+      return false;
+    }
+
+    @Override
+    public String toString()
+    {
+      return MessageFormat.format("DurableView[{0}]", durableLockingID);
+    }
+
+    public IOptionsContainer getContainer()
+    {
+      return null;
+    }
+
+    public void addListener(IListener listener)
+    {
+    }
+
+    public void removeListener(IListener listener)
+    {
+    }
+
+    public boolean hasListeners()
+    {
+      return false;
+    }
+
+    public IListener[] getListeners()
+    {
+      return null;
+    }
+
+    public Options options()
+    {
+      return this;
+    }
+
+    public boolean isLockNotificationEnabled()
+    {
+      return false;
+    }
+
+    public void setLockNotificationEnabled(boolean enabled)
+    {
+    }
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  private final class DurableLockLoader implements LockArea.Handler
+  {
+    public DurableLockLoader()
+    {
+    }
+
+    public boolean handleLockArea(LockArea area)
+    {
+      String durableLockingID = area.getDurableLockingID();
+      IView view = durableViews.get(durableLockingID);
+      if (view == null)
+      {
+        view = new DurableView(durableLockingID);
+        durableViews.put(durableLockingID, (DurableView)view);
+      }
+
+      Collection<Object> readLocks = new ArrayList<Object>();
+      Collection<Object> writeLocks = new ArrayList<Object>();
+      Collection<Object> writeOptions = new ArrayList<Object>();
+      for (Entry<CDOID, LockGrade> entry : area.getLocks().entrySet())
+      {
+        Object key = getLockKey(entry.getKey(), area.getBranch());
+        LockGrade grade = entry.getValue();
+        if (grade.isRead())
+        {
+          readLocks.add(key);
+        }
+
+        if (grade.isWrite())
+        {
+          writeLocks.add(key);
+        }
+
+        if (grade.isOption())
+        {
+          writeOptions.add(key);
+        }
+      }
+
+      try
+      {
+        lock(LockType.READ, view, readLocks, 1000L);
+        lock(LockType.WRITE, view, writeLocks, 1000L);
+        lock(LockType.OPTION, view, writeOptions, 1000L);
+      }
+      catch (InterruptedException ex)
+      {
+        throw WrappedException.wrap(ex);
+      }
+
+      return true;
+    }
+  }
+
+  public LockGrade getLockGrade(Object key)
+  {
+    LockState<Object, IView> lockState = getObjectToLocksMap().get(key);
+    LockGrade grade = LockGrade.NONE;
+    if (lockState != null)
+    {
+      for (LockType type : LockType.values())
+      {
+        if (lockState.hasLock(type))
+        {
+          grade = grade.getUpdated(type, true);
+        }
+      }
+    }
+    return grade;
+  }
+
+  private IView getView(String lockAreaID)
+  {
+    IView view = openViews.get(lockAreaID);
+    if (view == null)
+    {
+      view = durableViews.get(lockAreaID);
+    }
+    return view;
+  }
+
+  private LockArea getLockAreaNoEx(String durableLockingID)
+  {
+    try
+    {
+      return getLockArea(durableLockingID);
+    }
+    catch (LockAreaNotFoundException e)
+    {
+      return null;
+    }
+  }
+
+  public void updateLockArea(LockArea lockArea)
+  {
+    String durableLockingID = lockArea.getDurableLockingID();
+    DurableLocking2 accessor = getDurableLocking2();
+
+    if (lockArea.isMissing())
+    {
+      LockArea localLockArea = getLockAreaNoEx(durableLockingID);
+      if (localLockArea != null && localLockArea.getLocks().size() > 0)
+      {
+        accessor.deleteLockArea(durableLockingID);
+        DurableView deletedView = durableViews.remove(durableLockingID);
+        CheckUtil.checkNull(deletedView, "deletedView");
+      }
+    }
+    else
+    {
+      accessor.updateLockArea(lockArea);
+      IView view = getView(durableLockingID);
+      if (view != null)
+      {
+        unlock2(view);
+      }
+      new DurableLockLoader().handleLockArea(lockArea);
+    }
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/QueryManager.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/QueryManager.java
new file mode 100644
index 0000000..963092d
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/QueryManager.java
@@ -0,0 +1,319 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Simon McDuff - initial API and implementation
+ *    Eike Stepper - maintenance
+ */
+package org.eclipse.emf.cdo.internal.server;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.util.CDOQueryInfo;
+import org.eclipse.emf.cdo.internal.server.bundle.OM;
+import org.eclipse.emf.cdo.server.IQueryContext;
+import org.eclipse.emf.cdo.server.IQueryHandler;
+import org.eclipse.emf.cdo.server.IRepository;
+import org.eclipse.emf.cdo.server.IView;
+import org.eclipse.emf.cdo.server.StoreThreadLocal;
+import org.eclipse.emf.cdo.spi.common.branch.CDOBranchUtil;
+import org.eclipse.emf.cdo.spi.server.InternalQueryManager;
+import org.eclipse.emf.cdo.spi.server.InternalQueryResult;
+import org.eclipse.emf.cdo.spi.server.InternalRepository;
+import org.eclipse.emf.cdo.spi.server.InternalSession;
+import org.eclipse.emf.cdo.spi.server.InternalView;
+
+import org.eclipse.net4j.util.container.IContainerDelta.Kind;
+import org.eclipse.net4j.util.container.SingleDeltaContainerEvent;
+import org.eclipse.net4j.util.event.IEvent;
+import org.eclipse.net4j.util.event.IListener;
+import org.eclipse.net4j.util.lifecycle.Lifecycle;
+import org.eclipse.net4j.util.om.trace.ContextTracer;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+/**
+ * @author Simon McDuff
+ * @since 2.0
+ */
+public class QueryManager extends Lifecycle implements InternalQueryManager
+{
+  private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_SESSION, QueryManager.class);
+
+  private InternalRepository repository;
+
+  private Map<Integer, QueryContext> queryContexts = new ConcurrentHashMap<Integer, QueryContext>();
+
+  private ExecutorService executors;
+
+  private boolean shutdownExecutorService;
+
+  private int nextQuery;
+
+  private boolean allowInterruptRunningQueries = true;
+
+  public QueryManager()
+  {
+  }
+
+  public InternalRepository getRepository()
+  {
+    return repository;
+  }
+
+  public void setRepository(InternalRepository repository)
+  {
+    this.repository = repository;
+
+    String value = repository.getProperties().get(IRepository.Props.ALLOW_INTERRUPT_RUNNING_QUERIES);
+    if (value != null)
+    {
+      allowInterruptRunningQueries = Boolean.parseBoolean(value);
+    }
+  }
+
+  public synchronized ExecutorService getExecutors()
+  {
+    if (executors == null)
+    {
+      shutdownExecutorService = true;
+      executors = Executors.newFixedThreadPool(10);
+    }
+
+    return executors;
+  }
+
+  public synchronized void setExecutors(ExecutorService executors)
+  {
+    if (shutdownExecutorService)
+    {
+      this.executors.shutdown();
+      shutdownExecutorService = false;
+    }
+
+    this.executors = executors;
+  }
+
+  public InternalQueryResult execute(InternalView view, CDOQueryInfo queryInfo)
+  {
+    InternalQueryResult queryResult = new QueryResult(view, queryInfo, nextQuery());
+    QueryContext queryContext = new QueryContext(queryResult);
+    execute(queryContext);
+    return queryResult;
+  }
+
+  public boolean isRunning(int queryID)
+  {
+    QueryContext queryContext = queryContexts.get(queryID);
+    return queryContext != null;
+  }
+
+  public void cancel(int queryID)
+  {
+    QueryContext queryContext = queryContexts.get(queryID);
+    if (queryContext == null || queryContext.getFuture().isDone())
+    {
+      throw new RuntimeException("Query " + queryID + " is not running anymore"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.trace("Cancelling query for context: " + queryContext); //$NON-NLS-1$
+    }
+
+    queryContext.cancel();
+  }
+
+  public synchronized void register(final QueryContext queryContext)
+  {
+    queryContexts.put(queryContext.getQueryResult().getQueryID(), queryContext);
+    queryContext.addListener();
+  }
+
+  public synchronized void unregister(final QueryContext queryContext)
+  {
+    if (queryContexts.remove(queryContext.getQueryResult().getQueryID()) != null)
+    {
+      queryContext.removeListener();
+    }
+  }
+
+  public synchronized int nextQuery()
+  {
+    return nextQuery++;
+  }
+
+  @Override
+  protected void doDeactivate() throws Exception
+  {
+    super.doDeactivate();
+    setExecutors(null);
+  }
+
+  private Future<?> execute(QueryContext queryContext)
+  {
+    Future<?> future = getExecutors().submit(queryContext);
+    queryContext.setFuture(future);
+    register(queryContext);
+    return future;
+  }
+
+  /**
+   * @author Simon McDuff
+   * @since 2.0
+   */
+  private class QueryContext implements IQueryContext, Runnable
+  {
+    private CDOBranchPoint branchPoint;
+
+    private InternalQueryResult queryResult;
+
+    private boolean started;
+
+    private boolean cancelled;
+
+    private int resultCount;
+
+    private Future<?> future;
+
+    private IListener sessionListener = new IListener()
+    {
+      public void notifyEvent(IEvent event)
+      {
+        if (event instanceof SingleDeltaContainerEvent<?>)
+        {
+          IView view = getQueryResult().getView();
+          SingleDeltaContainerEvent<?> deltaEvent = (SingleDeltaContainerEvent<?>)event;
+          if (deltaEvent.getDeltaKind() == Kind.REMOVED && deltaEvent.getDeltaElement() == view)
+          {
+            // Cancel the query when view is closing
+            cancel();
+          }
+        }
+      }
+    };
+
+    public QueryContext(InternalQueryResult queryResult)
+    {
+      this.queryResult = queryResult;
+
+      // Remember the branchPoint because it can change
+      InternalView view = getView();
+
+      // long timeStamp = view.getTimeStamp();
+      // if (timeStamp == CDOBranchPoint.UNSPECIFIED_DATE && repository.isSupportingAudits())
+      // {
+      // timeStamp = repository.getTimeStamp();
+      // }
+      //
+      // branchPoint = view.getBranch().getPoint(timeStamp);
+
+      branchPoint = CDOBranchUtil.copyBranchPoint(view);
+    }
+
+    public InternalQueryResult getQueryResult()
+    {
+      return queryResult;
+    }
+
+    public InternalView getView()
+    {
+      return queryResult.getView();
+    }
+
+    public CDOBranch getBranch()
+    {
+      return branchPoint.getBranch();
+    }
+
+    public long getTimeStamp()
+    {
+      return branchPoint.getTimeStamp();
+    }
+
+    public Future<?> getFuture()
+    {
+      return future;
+    }
+
+    public void setFuture(Future<?> future)
+    {
+      this.future = future;
+    }
+
+    public void cancel()
+    {
+      cancelled = true;
+      if (future != null)
+      {
+        future.cancel(allowInterruptRunningQueries);
+      }
+
+      if (!started)
+      {
+        unregister(this);
+      }
+    }
+
+    public int getResultCount()
+    {
+      return resultCount;
+    }
+
+    public boolean addResult(Object object)
+    {
+      if (resultCount == 0)
+      {
+        throw new IllegalStateException("Maximum number of results exceeded"); //$NON-NLS-1$
+      }
+
+      queryResult.getQueue().add(object);
+      return !cancelled && --resultCount > 0;
+    }
+
+    public void run()
+    {
+      InternalSession session = queryResult.getView().getSession();
+      StoreThreadLocal.setSession(session);
+
+      try
+      {
+        started = true;
+        CDOQueryInfo info = queryResult.getQueryInfo();
+        resultCount = info.getMaxResults() < 0 ? Integer.MAX_VALUE : info.getMaxResults();
+        IQueryHandler handler = repository.getQueryHandler(info);
+        handler.executeQuery(info, this);
+      }
+      catch (Throwable exception)
+      {
+        queryResult.getQueue().setException(exception);
+      }
+      finally
+      {
+        queryResult.getQueue().close();
+        unregister(this);
+        StoreThreadLocal.release();
+      }
+    }
+
+    public void addListener()
+    {
+      InternalView view = getQueryResult().getView();
+      view.getSession().addListener(sessionListener);
+    }
+
+    public void removeListener()
+    {
+      InternalView view = getQueryResult().getView();
+      view.getSession().removeListener(sessionListener);
+    }
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/QueryResult.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/QueryResult.java
new file mode 100644
index 0000000..c5c17b4
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/QueryResult.java
@@ -0,0 +1,35 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Simon McDuff - initial API and implementation
+ *    Eike Stepper - maintenance
+ */
+package org.eclipse.emf.cdo.internal.server;
+
+import org.eclipse.emf.cdo.common.util.CDOQueryInfo;
+import org.eclipse.emf.cdo.spi.common.AbstractQueryResult;
+import org.eclipse.emf.cdo.spi.server.InternalQueryResult;
+import org.eclipse.emf.cdo.spi.server.InternalView;
+
+/**
+ * @author Simon McDuff
+ * @since 2.0
+ */
+public class QueryResult extends AbstractQueryResult<Object> implements InternalQueryResult
+{
+  public QueryResult(InternalView view, CDOQueryInfo queryInfo, int queryID)
+  {
+    super(view, queryInfo, queryID);
+  }
+
+  @Override
+  public InternalView getView()
+  {
+    return (InternalView)super.getView();
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Repository.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Repository.java
new file mode 100644
index 0000000..70dacf0
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Repository.java
@@ -0,0 +1,1923 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Simon McDuff - bug 201266
+ *    Simon McDuff - bug 233273
+ *    Simon McDuff - bug 233490
+ *    Stefan Winkler - changed order of determining audit and revision delta support.
+ *    Andre Dietisheim - bug 256649
+ */
+package org.eclipse.emf.cdo.internal.server;
+
+import org.eclipse.emf.cdo.common.CDOCommonView;
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchHandler;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.branch.CDOBranchVersion;
+import org.eclipse.emf.cdo.common.commit.CDOChangeSetData;
+import org.eclipse.emf.cdo.common.commit.CDOCommitData;
+import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
+import org.eclipse.emf.cdo.common.commit.CDOCommitInfoHandler;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.id.CDOIDGenerator;
+import org.eclipse.emf.cdo.common.id.CDOIDTemp;
+import org.eclipse.emf.cdo.common.id.CDOIDUtil;
+import org.eclipse.emf.cdo.common.lob.CDOLobHandler;
+import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
+import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo.Operation;
+import org.eclipse.emf.cdo.common.lock.CDOLockState;
+import org.eclipse.emf.cdo.common.lock.CDOLockUtil;
+import org.eclipse.emf.cdo.common.model.CDOModelUtil;
+import org.eclipse.emf.cdo.common.model.CDOPackageUnit;
+import org.eclipse.emf.cdo.common.model.EMFUtil;
+import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
+import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionFactory;
+import org.eclipse.emf.cdo.common.revision.CDORevisionHandler;
+import org.eclipse.emf.cdo.common.revision.CDORevisionKey;
+import org.eclipse.emf.cdo.common.revision.CDORevisionUtil;
+import org.eclipse.emf.cdo.common.util.CDOCommonUtil;
+import org.eclipse.emf.cdo.common.util.CDOQueryInfo;
+import org.eclipse.emf.cdo.common.util.RepositoryStateChangedEvent;
+import org.eclipse.emf.cdo.common.util.RepositoryTypeChangedEvent;
+import org.eclipse.emf.cdo.eresource.EresourcePackage;
+import org.eclipse.emf.cdo.etypes.EtypesPackage;
+import org.eclipse.emf.cdo.internal.common.model.CDOPackageRegistryImpl;
+import org.eclipse.emf.cdo.internal.server.bundle.OM;
+import org.eclipse.emf.cdo.server.IQueryHandler;
+import org.eclipse.emf.cdo.server.IQueryHandlerProvider;
+import org.eclipse.emf.cdo.server.IStore;
+import org.eclipse.emf.cdo.server.IStore.CanHandleClientAssignedIDs;
+import org.eclipse.emf.cdo.server.IStoreAccessor;
+import org.eclipse.emf.cdo.server.IStoreChunkReader;
+import org.eclipse.emf.cdo.server.IStoreChunkReader.Chunk;
+import org.eclipse.emf.cdo.server.ITransaction;
+import org.eclipse.emf.cdo.server.IView;
+import org.eclipse.emf.cdo.server.StoreThreadLocal;
+import org.eclipse.emf.cdo.spi.common.CDOReplicationContext;
+import org.eclipse.emf.cdo.spi.common.CDOReplicationInfo;
+import org.eclipse.emf.cdo.spi.common.branch.CDOBranchUtil;
+import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranchManager;
+import org.eclipse.emf.cdo.spi.common.commit.CDOChangeSetSegment;
+import org.eclipse.emf.cdo.spi.common.commit.CDOCommitInfoUtil;
+import org.eclipse.emf.cdo.spi.common.commit.CDORevisionAvailabilityInfo;
+import org.eclipse.emf.cdo.spi.common.commit.InternalCDOCommitInfoManager;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageInfo;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit;
+import org.eclipse.emf.cdo.spi.common.revision.DetachedCDORevision;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDOList;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager;
+import org.eclipse.emf.cdo.spi.common.revision.PointerCDORevision;
+import org.eclipse.emf.cdo.spi.common.revision.RevisionInfo;
+import org.eclipse.emf.cdo.spi.server.ContainerQueryHandlerProvider;
+import org.eclipse.emf.cdo.spi.server.InternalCommitContext;
+import org.eclipse.emf.cdo.spi.server.InternalCommitManager;
+import org.eclipse.emf.cdo.spi.server.InternalLockManager;
+import org.eclipse.emf.cdo.spi.server.InternalQueryManager;
+import org.eclipse.emf.cdo.spi.server.InternalRepository;
+import org.eclipse.emf.cdo.spi.server.InternalSession;
+import org.eclipse.emf.cdo.spi.server.InternalSessionManager;
+import org.eclipse.emf.cdo.spi.server.InternalStore;
+import org.eclipse.emf.cdo.spi.server.InternalTransaction;
+import org.eclipse.emf.cdo.spi.server.InternalView;
+
+import org.eclipse.emf.internal.cdo.object.CDOFactoryImpl;
+
+import org.eclipse.net4j.util.ReflectUtil.ExcludeFromDump;
+import org.eclipse.net4j.util.StringUtil;
+import org.eclipse.net4j.util.WrappedException;
+import org.eclipse.net4j.util.collection.MoveableList;
+import org.eclipse.net4j.util.collection.Pair;
+import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
+import org.eclipse.net4j.util.concurrent.RWOLockManager.LockState;
+import org.eclipse.net4j.util.concurrent.TimeoutRuntimeException;
+import org.eclipse.net4j.util.container.Container;
+import org.eclipse.net4j.util.container.IPluginContainer;
+import org.eclipse.net4j.util.lifecycle.LifecycleUtil;
+import org.eclipse.net4j.util.om.monitor.Monitor;
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+import org.eclipse.net4j.util.transaction.TransactionException;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.EcorePackage;
+import org.eclipse.emf.spi.cdo.CDOSessionProtocol.LockObjectsResult;
+import org.eclipse.emf.spi.cdo.CDOSessionProtocol.UnlockObjectsResult;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.Semaphore;
+
+/**
+ * @author Eike Stepper
+ * @since 2.0
+ */
+public class Repository extends Container<Object> implements InternalRepository
+{
+  private String name;
+
+  private String uuid;
+
+  private InternalStore store;
+
+  private Type type = Type.MASTER;
+
+  private State state = State.ONLINE;
+
+  private Map<String, String> properties;
+
+  private boolean supportingAudits;
+
+  private boolean supportingBranches;
+
+  private boolean supportingEcore;
+
+  private boolean ensuringReferentialIntegrity;
+
+  private IDGenerationLocation idGenerationLocation;
+
+  /**
+   * Must not be thread-bound to support XA commits.
+   */
+  private Semaphore packageRegistryCommitLock = new Semaphore(1);
+
+  private InternalCDOPackageRegistry packageRegistry;
+
+  private InternalCDOBranchManager branchManager;
+
+  private InternalCDORevisionManager revisionManager;
+
+  private InternalCDOCommitInfoManager commitInfoManager;
+
+  private InternalSessionManager sessionManager;
+
+  private InternalQueryManager queryManager;
+
+  private InternalCommitManager commitManager;
+
+  private InternalLockManager lockManager;
+
+  private IQueryHandlerProvider queryHandlerProvider;
+
+  private List<ReadAccessHandler> readAccessHandlers = new ArrayList<ReadAccessHandler>();
+
+  private List<WriteAccessHandler> writeAccessHandlers = new ArrayList<WriteAccessHandler>();
+
+  private List<CDOCommitInfoHandler> commitInfoHandlers = new ArrayList<CDOCommitInfoHandler>();
+
+  private EPackage[] initialPackages;
+
+  // Bugzilla 297940
+  private TimeStampAuthority timeStampAuthority = new TimeStampAuthority(this);
+
+  @ExcludeFromDump
+  private transient Object createBranchLock = new Object();
+
+  private boolean skipInitialization;
+
+  private CDOID rootResourceID;
+
+  public Repository()
+  {
+  }
+
+  public String getName()
+  {
+    return name;
+  }
+
+  public void setName(String name)
+  {
+    this.name = name;
+  }
+
+  public String getUUID()
+  {
+    if (uuid == null)
+    {
+      uuid = getProperties().get(Props.OVERRIDE_UUID);
+      if (uuid == null)
+      {
+        uuid = UUID.randomUUID().toString();
+      }
+      else if (uuid.length() == 0)
+      {
+        uuid = getName();
+      }
+    }
+
+    return uuid;
+  }
+
+  public InternalStore getStore()
+  {
+    return store;
+  }
+
+  public void setStore(InternalStore store)
+  {
+    this.store = store;
+  }
+
+  public Type getType()
+  {
+    return type;
+  }
+
+  public void setType(Type type)
+  {
+    checkArg(type, "type"); //$NON-NLS-1$
+    if (this.type != type)
+    {
+      changingType(this.type, type);
+    }
+  }
+
+  protected void changingType(Type oldType, Type newType)
+  {
+    type = newType;
+    fireEvent(new RepositoryTypeChangedEvent(this, oldType, newType));
+
+    if (sessionManager != null)
+    {
+      sessionManager.sendRepositoryTypeNotification(oldType, newType);
+    }
+  }
+
+  public State getState()
+  {
+    return state;
+  }
+
+  public void setState(State state)
+  {
+    checkArg(state, "state"); //$NON-NLS-1$
+    if (this.state != state)
+    {
+      changingState(this.state, state);
+    }
+  }
+
+  protected void changingState(State oldState, State newState)
+  {
+    state = newState;
+    fireEvent(new RepositoryStateChangedEvent(this, oldState, newState));
+
+    if (sessionManager != null)
+    {
+      sessionManager.sendRepositoryStateNotification(oldState, newState, getRootResourceID());
+    }
+  }
+
+  public synchronized Map<String, String> getProperties()
+  {
+    if (properties == null)
+    {
+      properties = new HashMap<String, String>();
+    }
+
+    return properties;
+  }
+
+  public synchronized void setProperties(Map<String, String> properties)
+  {
+    this.properties = properties;
+  }
+
+  public boolean isSupportingAudits()
+  {
+    return supportingAudits;
+  }
+
+  public boolean isSupportingBranches()
+  {
+    return supportingBranches;
+  }
+
+  public boolean isSupportingEcore()
+  {
+    return supportingEcore;
+  }
+
+  public boolean isEnsuringReferentialIntegrity()
+  {
+    return ensuringReferentialIntegrity;
+  }
+
+  public IDGenerationLocation getIDGenerationLocation()
+  {
+    return idGenerationLocation;
+  }
+
+  public String getStoreType()
+  {
+    return store.getType();
+  }
+
+  public Set<CDOID.ObjectType> getObjectIDTypes()
+  {
+    return store.getObjectIDTypes();
+  }
+
+  public CDOID getRootResourceID()
+  {
+    return rootResourceID;
+  }
+
+  public void setRootResourceID(CDOID rootResourceID)
+  {
+    this.rootResourceID = rootResourceID;
+  }
+
+  public Object processPackage(Object value)
+  {
+    CDOFactoryImpl.prepareDynamicEPackage(value);
+    return value;
+  }
+
+  public EPackage[] loadPackages(CDOPackageUnit packageUnit)
+  {
+    IStoreAccessor accessor = StoreThreadLocal.getAccessor();
+    return accessor.loadPackageUnit((InternalCDOPackageUnit)packageUnit);
+  }
+
+  public Pair<Integer, Long> createBranch(int branchID, BranchInfo branchInfo)
+  {
+    if (!isSupportingBranches())
+    {
+      throw new IllegalStateException("Branching is not supported by " + this);
+    }
+
+    long baseTimeStamp = branchInfo.getBaseTimeStamp();
+    if (baseTimeStamp == CDOBranchPoint.UNSPECIFIED_DATE)
+    {
+      baseTimeStamp = getTimeStamp();
+      branchInfo = new BranchInfo(branchInfo.getName(), branchInfo.getBaseBranchID(), baseTimeStamp);
+    }
+
+    synchronized (createBranchLock)
+    {
+      IStoreAccessor accessor = StoreThreadLocal.getAccessor();
+      return accessor.createBranch(branchID, branchInfo);
+    }
+  }
+
+  public BranchInfo loadBranch(int branchID)
+  {
+    IStoreAccessor accessor = StoreThreadLocal.getAccessor();
+    return accessor.loadBranch(branchID);
+  }
+
+  public SubBranchInfo[] loadSubBranches(int branchID)
+  {
+    IStoreAccessor accessor = StoreThreadLocal.getAccessor();
+    return accessor.loadSubBranches(branchID);
+  }
+
+  public int loadBranches(int startID, int endID, CDOBranchHandler branchHandler)
+  {
+    IStoreAccessor accessor = StoreThreadLocal.getAccessor();
+    return accessor.loadBranches(startID, endID, branchHandler);
+  }
+
+  public void loadCommitInfos(CDOBranch branch, long startTime, long endTime, CDOCommitInfoHandler handler)
+  {
+    IStoreAccessor accessor = StoreThreadLocal.getAccessor();
+    accessor.loadCommitInfos(branch, startTime, endTime, handler);
+  }
+
+  public CDOCommitData loadCommitData(long timeStamp)
+  {
+    IStoreAccessor accessor = StoreThreadLocal.getAccessor();
+    return accessor.loadCommitData(timeStamp);
+  }
+
+  public List<InternalCDORevision> loadRevisions(List<RevisionInfo> infos, CDOBranchPoint branchPoint,
+      int referenceChunk, int prefetchDepth)
+  {
+    for (RevisionInfo info : infos)
+    {
+      CDOID id = info.getID();
+      RevisionInfo.Type type = info.getType();
+      switch (type)
+      {
+      case AVAILABLE_NORMAL: // direct == false
+      {
+        RevisionInfo.Available.Normal availableInfo = (RevisionInfo.Available.Normal)info;
+        checkArg(availableInfo.isDirect() == false, "Load is not needed");
+        break;
+      }
+
+      case AVAILABLE_POINTER: // direct == false || target == null
+      {
+        RevisionInfo.Available.Pointer pointerInfo = (RevisionInfo.Available.Pointer)info;
+        boolean needsTarget = !pointerInfo.hasTarget();
+        checkArg(pointerInfo.isDirect() == false || needsTarget, "Load is not needed");
+
+        if (needsTarget)
+        {
+          CDOBranchVersion targetBranchVersion = pointerInfo.getTargetBranchVersion();
+          InternalCDORevision target = loadRevisionByVersion(id, targetBranchVersion, referenceChunk);
+          PointerCDORevision pointer = new PointerCDORevision(target.getEClass(), id, pointerInfo
+              .getAvailableBranchVersion().getBranch(), CDORevision.UNSPECIFIED_DATE, target);
+
+          info.setResult(target);
+          info.setSynthetic(pointer);
+          continue;
+        }
+
+        break;
+      }
+
+      case AVAILABLE_DETACHED: // direct == false
+      {
+        RevisionInfo.Available.Detached detachedInfo = (RevisionInfo.Available.Detached)info;
+        checkArg(detachedInfo.isDirect() == false, "Load is not needed");
+        break;
+      }
+
+      case MISSING:
+      {
+        break;
+      }
+
+      default:
+        throw new IllegalStateException("Invalid revision info type: " + type);
+      }
+
+      IStoreAccessor accessor = StoreThreadLocal.getAccessor();
+      InternalCDORevision revision = accessor.readRevision(id, branchPoint, referenceChunk, revisionManager);
+      if (revision == null)
+      {
+        if (isSupportingAudits())
+        {
+          // Case "Pointer"?
+          InternalCDORevision target = loadRevisionTarget(id, branchPoint, referenceChunk, accessor);
+          if (target != null)
+          {
+            CDOBranch branch = branchPoint.getBranch();
+            long revised = loadRevisionRevised(id, branch);
+            PointerCDORevision pointer = new PointerCDORevision(target.getEClass(), id, branch, revised, target);
+            info.setSynthetic(pointer);
+          }
+
+          info.setResult(target);
+        }
+        else
+        {
+          DetachedCDORevision detachedRevision = new DetachedCDORevision(EcorePackage.Literals.ECLASS, id,
+              branchPoint.getBranch(), 0, CDORevision.UNSPECIFIED_DATE);
+          info.setSynthetic(detachedRevision);
+        }
+      }
+      else if (revision instanceof DetachedCDORevision)
+      {
+        DetachedCDORevision detached = (DetachedCDORevision)revision;
+        info.setSynthetic(detached);
+      }
+      else
+      {
+        revision.freeze();
+        info.setResult(revision);
+      }
+    }
+
+    return null;
+  }
+
+  private InternalCDORevision loadRevisionTarget(CDOID id, CDOBranchPoint branchPoint, int referenceChunk,
+      IStoreAccessor accessor)
+  {
+    CDOBranch branch = branchPoint.getBranch();
+    while (!branch.isMainBranch())
+    {
+      branchPoint = branch.getBase();
+      branch = branchPoint.getBranch();
+
+      InternalCDORevision revision = accessor.readRevision(id, branchPoint, referenceChunk, revisionManager);
+      if (revision != null)
+      {
+        revision.freeze();
+        return revision;
+      }
+    }
+
+    return null;
+  }
+
+  private long loadRevisionRevised(CDOID id, CDOBranch branch)
+  {
+    InternalCDORevision revision = loadRevisionByVersion(id, branch.getVersion(CDORevision.FIRST_VERSION),
+        CDORevision.UNCHUNKED);
+    if (revision != null)
+    {
+      return revision.getTimeStamp() - 1;
+    }
+
+    return CDORevision.UNSPECIFIED_DATE;
+  }
+
+  public InternalCDORevision loadRevisionByVersion(CDOID id, CDOBranchVersion branchVersion, int referenceChunk)
+  {
+    IStoreAccessor accessor = StoreThreadLocal.getAccessor();
+    return accessor.readRevisionByVersion(id, branchVersion, referenceChunk, revisionManager);
+  }
+
+  protected void ensureChunks(InternalCDORevision revision, int referenceChunk, IStoreAccessor accessor)
+  {
+    EClass eClass = revision.getEClass();
+    EStructuralFeature[] features = CDOModelUtil.getAllPersistentFeatures(eClass);
+    for (int i = 0; i < features.length; i++)
+    {
+      EStructuralFeature feature = features[i];
+      if (feature.isMany())
+      {
+        MoveableList<Object> list = revision.getList(feature);
+        int chunkEnd = Math.min(referenceChunk, list.size());
+        accessor = ensureChunk(revision, feature, accessor, list, 0, chunkEnd);
+      }
+    }
+  }
+
+  public IStoreAccessor ensureChunk(InternalCDORevision revision, EStructuralFeature feature, int chunkStart,
+      int chunkEnd)
+  {
+    MoveableList<Object> list = revision.getList(feature);
+    chunkEnd = Math.min(chunkEnd, list.size());
+    return ensureChunk(revision, feature, StoreThreadLocal.getAccessor(), list, chunkStart, chunkEnd);
+  }
+
+  protected IStoreAccessor ensureChunk(InternalCDORevision revision, EStructuralFeature feature,
+      IStoreAccessor accessor, MoveableList<Object> list, int chunkStart, int chunkEnd)
+  {
+    IStoreChunkReader chunkReader = null;
+    int fromIndex = -1;
+    for (int j = chunkStart; j < chunkEnd; j++)
+    {
+      if (list.get(j) == InternalCDOList.UNINITIALIZED)
+      {
+        if (fromIndex == -1)
+        {
+          fromIndex = j;
+        }
+      }
+      else
+      {
+        if (fromIndex != -1)
+        {
+          if (chunkReader == null)
+          {
+            if (accessor == null)
+            {
+              accessor = StoreThreadLocal.getAccessor();
+            }
+
+            chunkReader = accessor.createChunkReader(revision, feature);
+          }
+
+          int toIndex = j;
+          if (fromIndex == toIndex - 1)
+          {
+            chunkReader.addSimpleChunk(fromIndex);
+          }
+          else
+          {
+            chunkReader.addRangedChunk(fromIndex, toIndex);
+          }
+
+          fromIndex = -1;
+        }
+      }
+    }
+
+    // Add last chunk
+    if (fromIndex != -1)
+    {
+      if (chunkReader == null)
+      {
+        if (accessor == null)
+        {
+          accessor = StoreThreadLocal.getAccessor();
+        }
+
+        chunkReader = accessor.createChunkReader(revision, feature);
+      }
+
+      int toIndex = chunkEnd;
+      if (fromIndex == toIndex - 1)
+      {
+        chunkReader.addSimpleChunk(fromIndex);
+      }
+      else
+      {
+        chunkReader.addRangedChunk(fromIndex, toIndex);
+      }
+    }
+
+    if (chunkReader != null)
+    {
+      InternalCDOList cdoList = list instanceof InternalCDOList ? (InternalCDOList)list : null;
+
+      List<Chunk> chunks = chunkReader.executeRead();
+      for (Chunk chunk : chunks)
+      {
+        int startIndex = chunk.getStartIndex();
+        for (int indexInChunk = 0; indexInChunk < chunk.size(); indexInChunk++)
+        {
+          Object id = chunk.get(indexInChunk);
+          if (cdoList != null)
+          {
+            cdoList.setWithoutFrozenCheck(startIndex + indexInChunk, id);
+          }
+          else
+          {
+            list.set(startIndex + indexInChunk, id);
+          }
+        }
+      }
+    }
+
+    return accessor;
+  }
+
+  public InternalCDOPackageRegistry getPackageRegistry(boolean considerCommitContext)
+  {
+    if (considerCommitContext)
+    {
+      IStoreAccessor.CommitContext commitContext = StoreThreadLocal.getCommitContext();
+      if (commitContext != null)
+      {
+        InternalCDOPackageRegistry contextualPackageRegistry = commitContext.getPackageRegistry();
+        if (contextualPackageRegistry != null)
+        {
+          return contextualPackageRegistry;
+        }
+      }
+    }
+
+    return packageRegistry;
+  }
+
+  public Semaphore getPackageRegistryCommitLock()
+  {
+    return packageRegistryCommitLock;
+  }
+
+  public InternalCDOPackageRegistry getPackageRegistry()
+  {
+    return getPackageRegistry(true);
+  }
+
+  public void setPackageRegistry(InternalCDOPackageRegistry packageRegistry)
+  {
+    checkInactive();
+    this.packageRegistry = packageRegistry;
+  }
+
+  public InternalSessionManager getSessionManager()
+  {
+    return sessionManager;
+  }
+
+  /**
+   * @since 2.0
+   */
+  public void setSessionManager(InternalSessionManager sessionManager)
+  {
+    checkInactive();
+    this.sessionManager = sessionManager;
+  }
+
+  public InternalCDOBranchManager getBranchManager()
+  {
+    return branchManager;
+  }
+
+  public void setBranchManager(InternalCDOBranchManager branchManager)
+  {
+    checkInactive();
+    this.branchManager = branchManager;
+  }
+
+  public InternalCDOCommitInfoManager getCommitInfoManager()
+  {
+    return commitInfoManager;
+  }
+
+  public void setCommitInfoManager(InternalCDOCommitInfoManager commitInfoManager)
+  {
+    checkInactive();
+    this.commitInfoManager = commitInfoManager;
+  }
+
+  public InternalCDORevisionManager getRevisionManager()
+  {
+    return revisionManager;
+  }
+
+  /**
+   * @since 2.0
+   */
+  public void setRevisionManager(InternalCDORevisionManager revisionManager)
+  {
+    checkInactive();
+    this.revisionManager = revisionManager;
+  }
+
+  /**
+   * @since 2.0
+   */
+  public InternalQueryManager getQueryManager()
+  {
+    return queryManager;
+  }
+
+  /**
+   * @since 2.0
+   */
+  public void setQueryManager(InternalQueryManager queryManager)
+  {
+    checkInactive();
+    this.queryManager = queryManager;
+  }
+
+  /**
+   * @since 2.0
+   */
+  public InternalCommitManager getCommitManager()
+  {
+    return commitManager;
+  }
+
+  /**
+   * @since 2.0
+   */
+  public void setCommitManager(InternalCommitManager commitManager)
+  {
+    checkInactive();
+    this.commitManager = commitManager;
+  }
+
+  /**
+   * @since 2.0
+   */
+  public InternalLockManager getLockManager()
+  {
+    return lockManager;
+  }
+
+  /**
+   * @since 2.0
+   */
+  public void setLockManager(InternalLockManager lockManager)
+  {
+    checkInactive();
+    this.lockManager = lockManager;
+  }
+
+  public InternalCommitContext createCommitContext(InternalTransaction transaction)
+  {
+    return new TransactionCommitContext(transaction);
+  }
+
+  public long getLastCommitTimeStamp()
+  {
+    return timeStampAuthority.getLastFinishedTimeStamp();
+  }
+
+  public void setLastCommitTimeStamp(long lastCommitTimeStamp)
+  {
+    timeStampAuthority.setLastFinishedTimeStamp(lastCommitTimeStamp);
+  }
+
+  public long waitForCommit(long timeout)
+  {
+    return timeStampAuthority.waitForCommit(timeout);
+  }
+
+  public long[] createCommitTimeStamp(OMMonitor monitor)
+  {
+    return timeStampAuthority.startCommit(CDOBranchPoint.UNSPECIFIED_DATE, monitor);
+  }
+
+  public long[] forceCommitTimeStamp(long override, OMMonitor monitor)
+  {
+    return timeStampAuthority.startCommit(override, monitor);
+  }
+
+  public void endCommit(long timestamp)
+  {
+    timeStampAuthority.endCommit(timestamp);
+  }
+
+  public void failCommit(long timestamp)
+  {
+    timeStampAuthority.failCommit(timestamp);
+  }
+
+  /**
+   * @since 4.0
+   */
+  public void addCommitInfoHandler(CDOCommitInfoHandler handler)
+  {
+    synchronized (commitInfoHandlers)
+    {
+      if (!commitInfoHandlers.contains(handler))
+      {
+        commitInfoHandlers.add(handler);
+      }
+    }
+  }
+
+  /**
+   * @since 4.0
+   */
+  public void removeCommitInfoHandler(CDOCommitInfoHandler handler)
+  {
+    synchronized (commitInfoHandlers)
+    {
+      commitInfoHandlers.remove(handler);
+    }
+  }
+
+  public void sendCommitNotification(InternalSession sender, CDOCommitInfo commitInfo)
+  {
+    sessionManager.sendCommitNotification(sender, commitInfo);
+
+    CDOCommitInfoHandler[] handlers;
+    synchronized (commitInfoHandlers)
+    {
+      handlers = commitInfoHandlers.toArray(new CDOCommitInfoHandler[commitInfoHandlers.size()]);
+    }
+
+    for (CDOCommitInfoHandler handler : handlers)
+    {
+      try
+      {
+        handler.handleCommitInfo(commitInfo);
+      }
+      catch (Exception ex)
+      {
+        OM.LOG.error(ex);
+      }
+    }
+  }
+
+  /**
+   * @since 2.0
+   */
+  public IQueryHandlerProvider getQueryHandlerProvider()
+  {
+    return queryHandlerProvider;
+  }
+
+  /**
+   * @since 2.0
+   */
+  public void setQueryHandlerProvider(IQueryHandlerProvider queryHandlerProvider)
+  {
+    this.queryHandlerProvider = queryHandlerProvider;
+  }
+
+  /**
+   * @since 2.0
+   */
+  public synchronized IQueryHandler getQueryHandler(CDOQueryInfo info)
+  {
+    String language = info.getQueryLanguage();
+    if (CDOProtocolConstants.QUERY_LANGUAGE_RESOURCES.equals(language))
+    {
+      return new ResourcesQueryHandler();
+    }
+
+    if (CDOProtocolConstants.QUERY_LANGUAGE_XREFS.equals(language))
+    {
+      return new XRefsQueryHandler();
+    }
+
+    IStoreAccessor storeAccessor = StoreThreadLocal.getAccessor();
+    if (storeAccessor != null)
+    {
+      IQueryHandler handler = storeAccessor.getQueryHandler(info);
+      if (handler != null)
+      {
+        return handler;
+      }
+    }
+
+    if (queryHandlerProvider == null)
+    {
+      queryHandlerProvider = new ContainerQueryHandlerProvider(IPluginContainer.INSTANCE);
+    }
+
+    IQueryHandler handler = queryHandlerProvider.getQueryHandler(info);
+    if (handler != null)
+    {
+      return handler;
+    }
+
+    return null;
+  }
+
+  public Object[] getElements()
+  {
+    final Object[] elements = { packageRegistry, branchManager, revisionManager, sessionManager, queryManager,
+        commitManager, commitInfoManager, lockManager, store };
+    return elements;
+  }
+
+  @Override
+  public boolean isEmpty()
+  {
+    return false;
+  }
+
+  /**
+   * @since 2.0
+   */
+  public long getCreationTime()
+  {
+    return store.getCreationTime();
+  }
+
+  /**
+   * @since 2.0
+   */
+  public void validateTimeStamp(long timeStamp) throws IllegalArgumentException
+  {
+    long creationTimeStamp = getCreationTime();
+    if (timeStamp < creationTimeStamp)
+    {
+      throw new IllegalArgumentException(
+          MessageFormat
+              .format(
+                  "timeStamp ({0}) < repository creation time ({1})", CDOCommonUtil.formatTimeStamp(timeStamp), CDOCommonUtil.formatTimeStamp(creationTimeStamp))); //$NON-NLS-1$
+    }
+
+    long currentTimeStamp = getTimeStamp();
+    if (timeStamp > currentTimeStamp)
+    {
+      throw new IllegalArgumentException(
+          MessageFormat
+              .format(
+                  "timeStamp ({0}) > current time ({1})", CDOCommonUtil.formatTimeStamp(timeStamp), CDOCommonUtil.formatTimeStamp(currentTimeStamp))); //$NON-NLS-1$
+    }
+  }
+
+  public long getTimeStamp()
+  {
+    return System.currentTimeMillis();
+  }
+
+  /**
+   * @since 2.0
+   */
+  public void addHandler(Handler handler)
+  {
+    if (handler instanceof ReadAccessHandler)
+    {
+      synchronized (readAccessHandlers)
+      {
+        if (!readAccessHandlers.contains(handler))
+        {
+          readAccessHandlers.add((ReadAccessHandler)handler);
+        }
+      }
+    }
+
+    if (handler instanceof WriteAccessHandler)
+    {
+      synchronized (writeAccessHandlers)
+      {
+        if (!writeAccessHandlers.contains(handler))
+        {
+          writeAccessHandlers.add((WriteAccessHandler)handler);
+        }
+      }
+    }
+  }
+
+  /**
+   * @since 2.0
+   */
+  public void removeHandler(Handler handler)
+  {
+    if (handler instanceof ReadAccessHandler)
+    {
+      synchronized (readAccessHandlers)
+      {
+        readAccessHandlers.remove(handler);
+      }
+    }
+
+    if (handler instanceof WriteAccessHandler)
+    {
+      synchronized (writeAccessHandlers)
+      {
+        writeAccessHandlers.remove(handler);
+      }
+    }
+  }
+
+  /**
+   * @since 2.0
+   */
+  public void notifyReadAccessHandlers(InternalSession session, CDORevision[] revisions,
+      List<CDORevision> additionalRevisions)
+  {
+    ReadAccessHandler[] handlers;
+    synchronized (readAccessHandlers)
+    {
+      int size = readAccessHandlers.size();
+      if (size == 0)
+      {
+        return;
+      }
+
+      handlers = readAccessHandlers.toArray(new ReadAccessHandler[size]);
+    }
+
+    for (ReadAccessHandler handler : handlers)
+    {
+      // Do *not* protect against unchecked exceptions from handlers!
+      handler.handleRevisionsBeforeSending(session, revisions, additionalRevisions);
+    }
+  }
+
+  public void notifyWriteAccessHandlers(ITransaction transaction, IStoreAccessor.CommitContext commitContext,
+      boolean beforeCommit, OMMonitor monitor)
+  {
+    WriteAccessHandler[] handlers;
+    synchronized (writeAccessHandlers)
+    {
+      int size = writeAccessHandlers.size();
+      if (size == 0)
+      {
+        return;
+      }
+
+      handlers = writeAccessHandlers.toArray(new WriteAccessHandler[size]);
+    }
+
+    try
+    {
+      monitor.begin(handlers.length);
+      for (WriteAccessHandler handler : handlers)
+      {
+        try
+        {
+          if (beforeCommit)
+          {
+            handler.handleTransactionBeforeCommitting(transaction, commitContext, monitor.fork());
+          }
+          else
+          {
+            handler.handleTransactionAfterCommitted(transaction, commitContext, monitor.fork());
+          }
+        }
+        catch (RuntimeException ex)
+        {
+          if (!beforeCommit)
+          {
+            OM.LOG.error(ex);
+          }
+          else
+          {
+            // Do *not* protect against unchecked exceptions from handlers on before case!
+            throw ex;
+          }
+        }
+      }
+    }
+    finally
+    {
+      monitor.done();
+    }
+  }
+
+  public void setInitialPackages(EPackage... initialPackages)
+  {
+    checkInactive();
+    this.initialPackages = initialPackages;
+  }
+
+  public CDOReplicationInfo replicateRaw(CDODataOutput out, int lastReplicatedBranchID, long lastReplicatedCommitTime)
+      throws IOException
+  {
+    final int fromBranchID = lastReplicatedBranchID + 1;
+    final int toBranchID = getStore().getLastBranchID();
+
+    final long fromCommitTime = lastReplicatedCommitTime + 1L;
+    final long toCommitTime = getStore().getLastCommitTime();
+
+    out.writeInt(toBranchID);
+    out.writeLong(toCommitTime);
+
+    IStoreAccessor.Raw accessor = (IStoreAccessor.Raw)StoreThreadLocal.getAccessor();
+    accessor.rawExport(out, fromBranchID, toBranchID, fromCommitTime, toCommitTime);
+
+    return new CDOReplicationInfo()
+    {
+      public int getLastReplicatedBranchID()
+      {
+        return toBranchID;
+      }
+
+      public long getLastReplicatedCommitTime()
+      {
+        return toCommitTime;
+      }
+
+      public String[] getLockAreaIDs()
+      {
+        return null; // TODO (CD) Raw replication of lockAreas
+      }
+    };
+  }
+
+  public void replicate(CDOReplicationContext context)
+  {
+    int startID = context.getLastReplicatedBranchID() + 1;
+    branchManager.getBranches(startID, 0, context);
+
+    long startTime = context.getLastReplicatedCommitTime();
+    commitInfoManager.getCommitInfos(null, startTime + 1L, CDOBranchPoint.UNSPECIFIED_DATE, context);
+
+    lockManager.getLockAreas(null, context);
+  }
+
+  public CDOChangeSetData getChangeSet(CDOBranchPoint startPoint, CDOBranchPoint endPoint)
+  {
+    CDOChangeSetSegment[] segments = CDOChangeSetSegment.createFrom(startPoint, endPoint);
+
+    IStoreAccessor accessor = StoreThreadLocal.getAccessor();
+    Set<CDOID> ids = accessor.readChangeSet(new Monitor(), segments);
+
+    return CDORevisionUtil.createChangeSetData(ids, startPoint, endPoint, revisionManager);
+  }
+
+  public Set<CDOID> getMergeData(CDORevisionAvailabilityInfo targetInfo, CDORevisionAvailabilityInfo sourceInfo,
+      CDORevisionAvailabilityInfo targetBaseInfo, CDORevisionAvailabilityInfo sourceBaseInfo, OMMonitor monitor)
+  {
+    CDOBranchPoint target = targetInfo.getBranchPoint();
+    CDOBranchPoint source = sourceInfo.getBranchPoint();
+
+    monitor.begin(5);
+
+    try
+    {
+      IStoreAccessor accessor = StoreThreadLocal.getAccessor();
+      Set<CDOID> ids = new HashSet<CDOID>();
+
+      if (targetBaseInfo == null && sourceBaseInfo == null)
+      {
+        if (CDOBranchUtil.isContainedBy(source, target))
+        {
+          ids.addAll(accessor.readChangeSet(monitor.fork(), CDOChangeSetSegment.createFrom(source, target)));
+        }
+        else if (CDOBranchUtil.isContainedBy(target, source))
+        {
+          ids.addAll(accessor.readChangeSet(monitor.fork(), CDOChangeSetSegment.createFrom(target, source)));
+        }
+        else
+        {
+          CDOBranchPoint ancestor = CDOBranchUtil.getAncestor(target, source);
+          ids.addAll(accessor.readChangeSet(monitor.fork(), CDOChangeSetSegment.createFrom(ancestor, target)));
+          ids.addAll(accessor.readChangeSet(monitor.fork(), CDOChangeSetSegment.createFrom(ancestor, source)));
+        }
+      }
+      else
+      {
+        CDORevisionAvailabilityInfo sourceBaseInfoToUse = sourceBaseInfo == null ? targetBaseInfo : sourceBaseInfo;
+
+        ids.addAll(accessor.readChangeSet(monitor.fork(),
+            CDOChangeSetSegment.createFrom(targetBaseInfo.getBranchPoint(), target)));
+
+        ids.addAll(accessor.readChangeSet(monitor.fork(),
+            CDOChangeSetSegment.createFrom(sourceBaseInfoToUse.getBranchPoint(), source)));
+      }
+
+      loadMergeData(ids, targetInfo, monitor.fork());
+      loadMergeData(ids, sourceInfo, monitor.fork());
+
+      if (targetBaseInfo != null)
+      {
+        loadMergeData(ids, targetBaseInfo, monitor.fork());
+      }
+
+      if (sourceBaseInfo != null)
+      {
+        loadMergeData(ids, sourceBaseInfo, monitor.fork());
+      }
+
+      return ids;
+    }
+    finally
+    {
+      monitor.done();
+    }
+  }
+
+  private void loadMergeData(Set<CDOID> ids, CDORevisionAvailabilityInfo info, OMMonitor monitor)
+  {
+    int size = ids.size();
+    monitor.begin(size);
+
+    try
+    {
+      CDOBranchPoint branchPoint = info.getBranchPoint();
+      for (CDOID id : ids)
+      {
+        if (info.containsRevision(id))
+        {
+          info.removeRevision(id);
+        }
+        else
+        {
+          InternalCDORevision revision = getRevisionFromBranch(id, branchPoint);
+          if (revision != null)
+          {
+            info.addRevision(revision);
+          }
+          else
+          {
+            info.removeRevision(id);
+          }
+        }
+
+        monitor.worked();
+      }
+    }
+    finally
+    {
+      monitor.done();
+    }
+  }
+
+  private InternalCDORevision getRevisionFromBranch(CDOID id, CDOBranchPoint branchPoint)
+  {
+    InternalCDORevision revision = revisionManager.getRevision(id, branchPoint, CDORevision.UNCHUNKED,
+        CDORevision.DEPTH_NONE, true);
+    // if (revision == null || !ObjectUtil.equals(revision.getBranch(), branchPoint.getBranch()))
+    // {
+    // return null;
+    // }
+
+    return revision;
+  }
+
+  public void queryLobs(List<byte[]> ids)
+  {
+    IStoreAccessor accessor = StoreThreadLocal.getAccessor();
+    accessor.queryLobs(ids);
+  }
+
+  public void handleLobs(long fromTime, long toTime, CDOLobHandler handler) throws IOException
+  {
+    IStoreAccessor accessor = StoreThreadLocal.getAccessor();
+    accessor.handleLobs(fromTime, toTime, handler);
+  }
+
+  public void loadLob(byte[] id, OutputStream out) throws IOException
+  {
+    IStoreAccessor accessor = StoreThreadLocal.getAccessor();
+    accessor.loadLob(id, out);
+  }
+
+  public void handleRevisions(EClass eClass, CDOBranch branch, boolean exactBranch, long timeStamp, boolean exactTime,
+      final CDORevisionHandler handler)
+  {
+    CDORevisionHandler wrapper = handler;
+    if (!exactBranch && !branch.isMainBranch())
+    {
+      if (exactTime && timeStamp == CDOBranchPoint.UNSPECIFIED_DATE)
+      {
+        throw new IllegalArgumentException("Time stamp must be specified if exactBranch==false and exactTime==true");
+      }
+
+      wrapper = new CDORevisionHandler()
+      {
+        private Set<CDOID> handled = new HashSet<CDOID>();
+
+        public boolean handleRevision(CDORevision revision)
+        {
+          CDOID id = revision.getID();
+          if (handled.add(id))
+          {
+            return handler.handleRevision(revision);
+          }
+
+          return true;
+        }
+      };
+    }
+
+    IStoreAccessor accessor = StoreThreadLocal.getAccessor();
+    while (branch != null)
+    {
+      accessor.handleRevisions(eClass, branch, timeStamp, exactTime, wrapper);
+      if (exactBranch)
+      {
+        break;
+      }
+
+      CDOBranchPoint base = branch.getBase();
+      branch = base.getBranch();
+      timeStamp = base.getTimeStamp();
+    }
+  }
+
+  public static List<Object> revisionKeysToObjects(List<CDORevisionKey> revisionKeys, CDOBranch viewedBranch,
+      boolean isSupportingBranches)
+  {
+    List<Object> lockables = new ArrayList<Object>();
+    for (CDORevisionKey revKey : revisionKeys)
+    {
+      CDOID id = revKey.getID();
+      if (isSupportingBranches)
+      {
+        lockables.add(CDOIDUtil.createIDAndBranch(id, viewedBranch));
+      }
+      else
+      {
+        lockables.add(id);
+      }
+    }
+    return lockables;
+  }
+
+  public LockObjectsResult lock(InternalView view, LockType lockType, List<CDORevisionKey> revKeys, long timeout)
+  {
+    List<Object> lockables = revisionKeysToObjects(revKeys, view.getBranch(), isSupportingBranches());
+    return lock(view, lockType, lockables, revKeys, timeout);
+  }
+
+  protected LockObjectsResult lock(InternalView view, LockType type, List<Object> lockables,
+      List<CDORevisionKey> loadedRevs, long timeout)
+  {
+    List<LockState<Object, IView>> newLockStates = null;
+    try
+    {
+      newLockStates = lockManager.lock2(true, type, view, lockables, timeout);
+    }
+    catch (TimeoutRuntimeException ex)
+    {
+      return new LockObjectsResult(false, true, false, 0, new CDORevisionKey[0], new CDOLockState[0], getTimeStamp());
+    }
+    catch (InterruptedException ex)
+    {
+      throw WrappedException.wrap(ex);
+    }
+
+    long[] requiredTimestamp = { 0L };
+    CDORevisionKey[] staleRevisionsArray = checkStaleRevisions(view, loadedRevs, lockables, type, requiredTimestamp);
+
+    // If some of the clients' revisions are stale and it has passiveUpdates disabled,
+    // then the locks are useless so we release them and report the stale revisions
+    //
+    InternalSession session = view.getSession();
+    boolean staleNoUpdate = staleRevisionsArray.length > 0 && !session.isPassiveUpdateEnabled();
+    if (staleNoUpdate)
+    {
+      lockManager.unlock2(true, type, view, lockables);
+      return new LockObjectsResult(false, false, false, requiredTimestamp[0], staleRevisionsArray, new CDOLockState[0],
+          getTimeStamp());
+    }
+
+    CDOLockState[] cdoLockStates = toCDOLockStates(newLockStates);
+    sendLockNotifications(view, Operation.LOCK, type, cdoLockStates);
+
+    boolean waitForUpdate = staleRevisionsArray.length > 0;
+    return new LockObjectsResult(true, false, waitForUpdate, requiredTimestamp[0], staleRevisionsArray, cdoLockStates,
+        getTimeStamp());
+  }
+
+  private CDORevisionKey[] checkStaleRevisions(InternalView view, List<CDORevisionKey> revisionKeys,
+      List<Object> objectsToLock, LockType lockType, long[] requiredTimestamp)
+  {
+    List<CDORevisionKey> staleRevisions = new LinkedList<CDORevisionKey>();
+    if (revisionKeys != null)
+    {
+      InternalCDORevisionManager revManager = getRevisionManager();
+      CDOBranch viewedBranch = view.getBranch();
+      for (CDORevisionKey revKey : revisionKeys)
+      {
+        CDOID id = revKey.getID();
+        InternalCDORevision rev = revManager.getRevision(id, viewedBranch.getHead(), CDORevision.UNCHUNKED,
+            CDORevision.DEPTH_NONE, true);
+
+        if (rev == null)
+        {
+          lockManager.unlock2(true, lockType, view, objectsToLock);
+          throw new IllegalArgumentException(String.format("Object %s not found in branch %s (possibly detached)", id,
+              viewedBranch));
+        }
+
+        if (!revKey.equals(rev))
+        {
+          staleRevisions.add(revKey);
+          requiredTimestamp[0] = Math.max(requiredTimestamp[0], rev.getTimeStamp());
+        }
+      }
+    }
+
+    // Convert the list to an array, to satisfy the API later
+    //
+    CDORevisionKey[] staleRevisionsArray = new CDORevisionKey[staleRevisions.size()];
+    staleRevisions.toArray(staleRevisionsArray);
+
+    return staleRevisionsArray;
+  }
+
+  private void sendLockNotifications(IView view, Operation operation, LockType lockType, CDOLockState[] cdoLockStates)
+  {
+    long timestamp = getTimeStamp();
+    CDOLockChangeInfo lockChangeInfo = CDOLockUtil.createLockChangeInfo(timestamp, view, view.getBranch(), operation,
+        lockType, cdoLockStates);
+    getSessionManager().sendLockNotification((InternalSession)view.getSession(), lockChangeInfo);
+  }
+
+  // TODO (CD) This doesn't really belong here.. but getting it into CDOLockUtil isn't possible
+  public static CDOLockState[] toCDOLockStates(List<LockState<Object, IView>> lockStates)
+  {
+    CDOLockState[] cdoLockStates = new CDOLockState[lockStates.size()];
+    int i = 0;
+
+    for (LockState<Object, ? extends CDOCommonView> lockState : lockStates)
+    {
+      CDOLockState cdoLockState = CDOLockUtil.createLockState(lockState);
+      cdoLockStates[i++] = cdoLockState;
+    }
+
+    return cdoLockStates;
+  }
+
+  public UnlockObjectsResult unlock(InternalView view, LockType lockType, List<CDOID> objectIDs)
+  {
+    List<Object> unlockables = null;
+    if (objectIDs != null)
+    {
+      unlockables = new ArrayList<Object>(objectIDs.size());
+      CDOBranch branch = view.getBranch();
+      for (CDOID id : objectIDs)
+      {
+        Object key = supportingBranches ? CDOIDUtil.createIDAndBranch(id, branch) : id;
+        unlockables.add(key);
+      }
+    }
+
+    return doUnlock(view, lockType, unlockables);
+  }
+
+  protected UnlockObjectsResult doUnlock(InternalView view, LockType lockType, List<Object> unlockables)
+  {
+    List<LockState<Object, IView>> newLockStates = null;
+    if (lockType == null) // Signals an unlock-all operation
+    {
+      newLockStates = lockManager.unlock2(true, view);
+    }
+    else
+    {
+      newLockStates = lockManager.unlock2(true, lockType, view, unlockables);
+    }
+
+    long timestamp = getTimeStamp();
+    CDOLockState[] cdoLockStates = toCDOLockStates(newLockStates);
+    sendLockNotifications(view, Operation.UNLOCK, lockType, cdoLockStates);
+
+    return new UnlockObjectsResult(cdoLockStates, timestamp);
+  }
+
+  @Override
+  public String toString()
+  {
+    return MessageFormat.format("Repository[{0}]", name); //$NON-NLS-1$
+  }
+
+  public boolean isSkipInitialization()
+  {
+    return skipInitialization;
+  }
+
+  public void setSkipInitialization(boolean skipInitialization)
+  {
+    this.skipInitialization = skipInitialization;
+  }
+
+  protected void initProperties()
+  {
+    String valueAudits = properties.get(Props.SUPPORTING_AUDITS);
+    if (valueAudits != null)
+    {
+      supportingAudits = Boolean.valueOf(valueAudits);
+    }
+    else
+    {
+      supportingAudits = store.getRevisionTemporality() == IStore.RevisionTemporality.AUDITING;
+    }
+
+    String valueBranches = properties.get(Props.SUPPORTING_BRANCHES);
+    if (valueBranches != null)
+    {
+      supportingBranches = Boolean.valueOf(valueBranches);
+    }
+    else
+    {
+      supportingBranches = store.getRevisionParallelism() == IStore.RevisionParallelism.BRANCHING;
+    }
+
+    String valueEcore = properties.get(Props.SUPPORTING_ECORE);
+    if (valueEcore != null)
+    {
+      supportingEcore = Boolean.valueOf(valueEcore);
+    }
+
+    String valueIntegrity = properties.get(Props.ENSURE_REFERENTIAL_INTEGRITY);
+    if (valueIntegrity != null)
+    {
+      ensuringReferentialIntegrity = Boolean.valueOf(valueIntegrity);
+    }
+
+    String valueIDLocation = properties.get(Props.ID_GENERATION_LOCATION);
+    if (valueIDLocation != null)
+    {
+      idGenerationLocation = IDGenerationLocation.valueOf(valueIDLocation);
+    }
+
+    if (idGenerationLocation == null)
+    {
+      idGenerationLocation = IDGenerationLocation.STORE;
+    }
+  }
+
+  public void initSystemPackages()
+  {
+    IStoreAccessor writer = store.getWriter(null);
+    StoreThreadLocal.setAccessor(writer);
+
+    try
+    {
+      List<InternalCDOPackageUnit> units = new ArrayList<InternalCDOPackageUnit>();
+      units.add(initSystemPackage(EcorePackage.eINSTANCE));
+      units.add(initSystemPackage(EresourcePackage.eINSTANCE));
+      units.add(initSystemPackage(EtypesPackage.eINSTANCE));
+
+      if (initialPackages != null)
+      {
+        for (EPackage initialPackage : initialPackages)
+        {
+          if (!packageRegistry.containsKey(initialPackage.getNsURI()))
+          {
+            units.add(initSystemPackage(initialPackage));
+          }
+        }
+      }
+
+      InternalCDOPackageUnit[] systemUnits = units.toArray(new InternalCDOPackageUnit[units.size()]);
+      writer.writePackageUnits(systemUnits, new Monitor());
+      writer.commit(new Monitor());
+    }
+    finally
+    {
+      StoreThreadLocal.release();
+    }
+  }
+
+  protected InternalCDOPackageUnit initSystemPackage(EPackage ePackage)
+  {
+    EMFUtil.registerPackage(ePackage, packageRegistry);
+    InternalCDOPackageInfo packageInfo = packageRegistry.getPackageInfo(ePackage);
+
+    InternalCDOPackageUnit packageUnit = packageInfo.getPackageUnit();
+    packageUnit.setTimeStamp(store.getCreationTime());
+    packageUnit.setState(CDOPackageUnit.State.LOADED);
+    return packageUnit;
+  }
+
+  public void initMainBranch(InternalCDOBranchManager branchManager, long timeStamp)
+  {
+    branchManager.initMainBranch(false, timeStamp);
+  }
+
+  protected void initRootResource()
+  {
+    CDOBranchPoint head = branchManager.getMainBranch().getHead();
+
+    CDORevisionFactory factory = getRevisionManager().getFactory();
+    InternalCDORevision rootResource = (InternalCDORevision)factory
+        .createRevision(EresourcePackage.Literals.CDO_RESOURCE);
+
+    rootResource.setBranchPoint(head);
+    rootResource.setContainerID(CDOID.NULL);
+    rootResource.setContainingFeatureID(0);
+
+    CDOID id = createRootResourceID();
+    rootResource.setID(id);
+    rootResource.setResourceID(id);
+
+    InternalSession session = getSessionManager().openSession(null);
+    InternalTransaction transaction = session.openTransaction(1, head);
+    InternalCommitContext commitContext = new TransactionCommitContext(transaction)
+    {
+      @Override
+      protected long[] createTimeStamp(OMMonitor monitor)
+      {
+        InternalRepository repository = getTransaction().getSession().getManager().getRepository();
+        return repository.forceCommitTimeStamp(store.getCreationTime(), monitor);
+      }
+
+      @Override
+      public String getUserID()
+      {
+        return SYSTEM_USER_ID;
+      }
+
+      @Override
+      public String getCommitComment()
+      {
+        return "<initialize>"; //$NON-NLS-1$
+      }
+    };
+
+    commitContext.setNewObjects(new InternalCDORevision[] { rootResource });
+    commitContext.preWrite();
+
+    commitContext.write(new Monitor());
+    commitContext.commit(new Monitor());
+
+    String rollbackMessage = commitContext.getRollbackMessage();
+    if (rollbackMessage != null)
+    {
+      throw new TransactionException(rollbackMessage);
+    }
+
+    rootResourceID = id instanceof CDOIDTemp ? commitContext.getIDMappings().get(id) : id;
+
+    commitContext.postCommit(true);
+    session.close();
+  }
+
+  protected CDOID createRootResourceID()
+  {
+    if (getIDGenerationLocation() == IDGenerationLocation.STORE)
+    {
+      return CDOIDUtil.createTempObject(1);
+    }
+
+    return CDOIDGenerator.UUID.generateCDOID(null);
+  }
+
+  protected void readRootResource()
+  {
+    IStoreAccessor reader = store.getReader(null);
+    StoreThreadLocal.setAccessor(reader);
+
+    try
+    {
+      CDOBranchPoint head = branchManager.getMainBranch().getHead();
+      rootResourceID = reader.readResourceID(CDOID.NULL, null, head);
+    }
+    finally
+    {
+      StoreThreadLocal.release();
+    }
+  }
+
+  protected void readPackageUnits()
+  {
+    IStoreAccessor reader = store.getReader(null);
+    StoreThreadLocal.setAccessor(reader);
+
+    try
+    {
+      Collection<InternalCDOPackageUnit> packageUnits = reader.readPackageUnits();
+      for (InternalCDOPackageUnit packageUnit : packageUnits)
+      {
+        packageRegistry.putPackageUnit(packageUnit);
+      }
+    }
+    finally
+    {
+      StoreThreadLocal.release();
+    }
+  }
+
+  @Override
+  protected void doBeforeActivate() throws Exception
+  {
+    super.doBeforeActivate();
+    checkState(store, "store"); //$NON-NLS-1$
+    checkState(!StringUtil.isEmpty(name), "name is empty"); //$NON-NLS-1$
+    checkState(packageRegistry, "packageRegistry"); //$NON-NLS-1$
+    checkState(sessionManager, "sessionManager"); //$NON-NLS-1$
+    checkState(branchManager, "branchManager"); //$NON-NLS-1$
+    checkState(revisionManager, "revisionManager"); //$NON-NLS-1$
+    checkState(queryManager, "queryManager"); //$NON-NLS-1$
+    checkState(commitInfoManager, "commitInfoManager"); //$NON-NLS-1$
+    checkState(commitManager, "commitManager"); //$NON-NLS-1$
+    checkState(lockManager, "lockingManager"); //$NON-NLS-1$
+
+    packageRegistry.setReplacingDescriptors(true);
+    packageRegistry.setPackageProcessor(this);
+    packageRegistry.setPackageLoader(this);
+
+    branchManager.setBranchLoader(this);
+    branchManager.setTimeProvider(this);
+
+    revisionManager.setRevisionLoader(this);
+    sessionManager.setRepository(this);
+    queryManager.setRepository(this);
+    commitInfoManager.setCommitInfoLoader(this);
+    commitManager.setRepository(this);
+    lockManager.setRepository(this);
+    store.setRepository(this);
+  }
+
+  @Override
+  protected void doActivate() throws Exception
+  {
+    super.doActivate();
+
+    initProperties();
+    if (idGenerationLocation == IDGenerationLocation.CLIENT && !(store instanceof CanHandleClientAssignedIDs))
+    {
+      throw new IllegalStateException("Store can not handle client assigned IDs: " + store);
+    }
+
+    store.setRevisionTemporality(supportingAudits ? IStore.RevisionTemporality.AUDITING
+        : IStore.RevisionTemporality.NONE);
+    store.setRevisionParallelism(supportingBranches ? IStore.RevisionParallelism.BRANCHING
+        : IStore.RevisionParallelism.NONE);
+    revisionManager.setSupportingAudits(supportingAudits);
+    revisionManager.setSupportingBranches(supportingBranches);
+
+    LifecycleUtil.activate(store);
+    LifecycleUtil.activate(packageRegistry);
+    LifecycleUtil.activate(sessionManager);
+    LifecycleUtil.activate(revisionManager);
+    LifecycleUtil.activate(branchManager);
+    LifecycleUtil.activate(queryManager);
+    LifecycleUtil.activate(commitInfoManager);
+    LifecycleUtil.activate(commitManager);
+    LifecycleUtil.activate(queryHandlerProvider);
+
+    if (!skipInitialization)
+    {
+      long lastCommitTimeStamp = Math.max(store.getCreationTime(), store.getLastCommitTime());
+      timeStampAuthority.setLastFinishedTimeStamp(lastCommitTimeStamp);
+      initMainBranch(branchManager, lastCommitTimeStamp);
+
+      if (store.isFirstStart())
+      {
+        initSystemPackages();
+        initRootResource();
+      }
+      else
+      {
+        readPackageUnits();
+        readRootResource();
+      }
+
+      // This check does not work for CDOWorkspace:
+      // if (CDOIDUtil.isNull(rootResourceID))
+      // {
+      // throw new IllegalStateException("Root resource ID is null");
+      // }
+    }
+
+    LifecycleUtil.activate(lockManager); // Needs an initialized main branch / branch manager
+  }
+
+  @Override
+  protected void doDeactivate() throws Exception
+  {
+    LifecycleUtil.deactivate(lockManager);
+    LifecycleUtil.deactivate(queryHandlerProvider);
+    LifecycleUtil.deactivate(commitManager);
+    LifecycleUtil.deactivate(commitInfoManager);
+    LifecycleUtil.deactivate(queryManager);
+    LifecycleUtil.deactivate(revisionManager);
+    LifecycleUtil.deactivate(sessionManager);
+    LifecycleUtil.deactivate(store);
+    LifecycleUtil.deactivate(branchManager);
+    LifecycleUtil.deactivate(packageRegistry);
+    super.doDeactivate();
+  }
+
+  /**
+   * @author Eike Stepper
+   * @since 2.0
+   */
+  public static class Default extends Repository
+  {
+    public Default()
+    {
+    }
+
+    @Override
+    protected void doBeforeActivate() throws Exception
+    {
+      if (getPackageRegistry(false) == null)
+      {
+        setPackageRegistry(createPackageRegistry());
+      }
+
+      if (getSessionManager() == null)
+      {
+        setSessionManager(createSessionManager());
+      }
+
+      if (getBranchManager() == null)
+      {
+        setBranchManager(createBranchManager());
+      }
+
+      if (getRevisionManager() == null)
+      {
+        setRevisionManager(createRevisionManager());
+      }
+
+      if (getQueryManager() == null)
+      {
+        setQueryManager(createQueryManager());
+      }
+
+      if (getCommitInfoManager() == null)
+      {
+        setCommitInfoManager(createCommitInfoManager());
+      }
+
+      if (getCommitManager() == null)
+      {
+        setCommitManager(createCommitManager());
+      }
+
+      if (getLockManager() == null)
+      {
+        setLockManager(createLockManager());
+      }
+
+      super.doBeforeActivate();
+    }
+
+    protected InternalCDOPackageRegistry createPackageRegistry()
+    {
+      return new CDOPackageRegistryImpl();
+    }
+
+    protected InternalSessionManager createSessionManager()
+    {
+      return new SessionManager();
+    }
+
+    protected InternalCDOBranchManager createBranchManager()
+    {
+      return CDOBranchUtil.createBranchManager();
+    }
+
+    protected InternalCDORevisionManager createRevisionManager()
+    {
+      return (InternalCDORevisionManager)CDORevisionUtil.createRevisionManager();
+    }
+
+    protected InternalQueryManager createQueryManager()
+    {
+      return new QueryManager();
+    }
+
+    protected InternalCDOCommitInfoManager createCommitInfoManager()
+    {
+      return CDOCommitInfoUtil.createCommitInfoManager();
+    }
+
+    protected InternalCommitManager createCommitManager()
+    {
+      return new CommitManager();
+    }
+
+    protected InternalLockManager createLockManager()
+    {
+      return new LockManager();
+    }
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/ResourcesQueryHandler.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/ResourcesQueryHandler.java
new file mode 100644
index 0000000..81c653d
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/ResourcesQueryHandler.java
@@ -0,0 +1,146 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.internal.server;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants;
+import org.eclipse.emf.cdo.common.util.CDOQueryInfo;
+import org.eclipse.emf.cdo.server.IQueryContext;
+import org.eclipse.emf.cdo.server.IQueryHandler;
+import org.eclipse.emf.cdo.server.IStoreAccessor;
+import org.eclipse.emf.cdo.server.StoreThreadLocal;
+import org.eclipse.emf.cdo.spi.server.QueryHandlerFactory;
+
+import org.eclipse.net4j.util.factory.ProductCreationException;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author Eike Stepper
+ * @since 2.0
+ */
+public class ResourcesQueryHandler implements IQueryHandler
+{
+  public ResourcesQueryHandler()
+  {
+  }
+
+  public void executeQuery(CDOQueryInfo info, IQueryContext context)
+  {
+    IStoreAccessor accessor = StoreThreadLocal.getAccessor();
+    QueryContext resourcesContext = new QueryContext(info, context);
+    accessor.queryResources(resourcesContext);
+
+    CDOBranchPoint branchPoint = context;
+    CDOBranch branch = branchPoint.getBranch();
+    while (!branch.isMainBranch() && resourcesContext.getResourceIDs().size() < info.getMaxResults())
+    {
+      branchPoint = branch.getBase();
+      branch = branchPoint.getBranch();
+
+      resourcesContext.setBranchPoint(branchPoint);
+      accessor.queryResources(resourcesContext);
+    }
+  }
+
+  /**
+   * @author Eike Stepper
+   * @since 3.0
+   */
+  private static final class QueryContext implements IStoreAccessor.QueryResourcesContext
+  {
+    private CDOQueryInfo info;
+
+    private IQueryContext context;
+
+    private CDOBranchPoint branchPoint;
+
+    private Set<CDOID> resourceIDs = new HashSet<CDOID>();
+
+    public QueryContext(CDOQueryInfo info, IQueryContext context)
+    {
+      this.info = info;
+      this.context = context;
+      branchPoint = context;
+    }
+
+    public void setBranchPoint(CDOBranchPoint branchPoint)
+    {
+      this.branchPoint = branchPoint;
+    }
+
+    public Set<CDOID> getResourceIDs()
+    {
+      return resourceIDs;
+    }
+
+    public CDOBranch getBranch()
+    {
+      return branchPoint.getBranch();
+    }
+
+    public long getTimeStamp()
+    {
+      return branchPoint.getTimeStamp();
+    }
+
+    public CDOID getFolderID()
+    {
+      return (CDOID)info.getParameters().get(CDOProtocolConstants.QUERY_LANGUAGE_RESOURCES_FOLDER_ID);
+    }
+
+    public String getName()
+    {
+      return info.getQueryString();
+    }
+
+    public boolean exactMatch()
+    {
+      return (Boolean)info.getParameters().get(CDOProtocolConstants.QUERY_LANGUAGE_RESOURCES_EXACT_MATCH);
+    }
+
+    public int getMaxResults()
+    {
+      return info.getMaxResults();
+    }
+
+    public boolean addResource(CDOID resourceID)
+    {
+      if (resourceIDs.add(resourceID))
+      {
+        return context.addResult(resourceID);
+      }
+
+      return true;
+    }
+  }
+
+  /**
+   * @author Eike Stepper
+   * @since 2.0
+   */
+  public static class Factory extends QueryHandlerFactory
+  {
+    public Factory()
+    {
+      super(CDOProtocolConstants.QUERY_LANGUAGE_RESOURCES);
+    }
+
+    @Override
+    public ResourcesQueryHandler create(String description) throws ProductCreationException
+    {
+      return new ResourcesQueryHandler();
+    }
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/ServerCDOView.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/ServerCDOView.java
new file mode 100644
index 0000000..f551a61
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/ServerCDOView.java
@@ -0,0 +1,901 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.internal.server;
+
+import org.eclipse.emf.cdo.CDOObject;
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.commit.CDOChangeSetData;
+import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.id.CDOID.ObjectType;
+import org.eclipse.emf.cdo.common.id.CDOIDGenerator;
+import org.eclipse.emf.cdo.common.lob.CDOLobStore;
+import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
+import org.eclipse.emf.cdo.common.lock.CDOLockState;
+import org.eclipse.emf.cdo.common.model.CDOPackageUnit;
+import org.eclipse.emf.cdo.common.protocol.CDOAuthenticator;
+import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionKey;
+import org.eclipse.emf.cdo.common.revision.CDORevisionProvider;
+import org.eclipse.emf.cdo.server.IStoreAccessor;
+import org.eclipse.emf.cdo.session.CDORepositoryInfo;
+import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranch;
+import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranchManager;
+import org.eclipse.emf.cdo.spi.common.commit.CDORevisionAvailabilityInfo;
+import org.eclipse.emf.cdo.spi.common.commit.InternalCDOCommitInfoManager;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager;
+import org.eclipse.emf.cdo.spi.server.InternalRepository;
+import org.eclipse.emf.cdo.spi.server.InternalSession;
+import org.eclipse.emf.cdo.transaction.CDOTransaction;
+import org.eclipse.emf.cdo.util.CDOUtil;
+import org.eclipse.emf.cdo.view.CDOAdapterPolicy;
+import org.eclipse.emf.cdo.view.CDOFeatureAnalyzer;
+import org.eclipse.emf.cdo.view.CDOFetchRuleManager;
+import org.eclipse.emf.cdo.view.CDOInvalidationPolicy;
+import org.eclipse.emf.cdo.view.CDORevisionPrefetchingPolicy;
+import org.eclipse.emf.cdo.view.CDOStaleReferencePolicy;
+import org.eclipse.emf.cdo.view.CDOView;
+
+import org.eclipse.emf.internal.cdo.session.SessionUtil;
+import org.eclipse.emf.internal.cdo.view.AbstractCDOView;
+
+import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
+import org.eclipse.net4j.util.event.IListener;
+import org.eclipse.net4j.util.lifecycle.LifecycleException;
+import org.eclipse.net4j.util.lifecycle.LifecycleState;
+import org.eclipse.net4j.util.ref.ReferenceType;
+import org.eclipse.net4j.util.ref.ReferenceValueMap;
+
+import org.eclipse.emf.common.notify.Adapter;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
+import org.eclipse.emf.spi.cdo.CDOSessionProtocol;
+import org.eclipse.emf.spi.cdo.CDOSessionProtocol.RefreshSessionResult;
+import org.eclipse.emf.spi.cdo.InternalCDOObject;
+import org.eclipse.emf.spi.cdo.InternalCDORemoteSessionManager;
+import org.eclipse.emf.spi.cdo.InternalCDOSession;
+import org.eclipse.emf.spi.cdo.InternalCDOTransaction;
+import org.eclipse.emf.spi.cdo.InternalCDOView;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author Eike Stepper
+ */
+public class ServerCDOView extends AbstractCDOView implements org.eclipse.emf.cdo.view.CDOView.Options
+{
+  private static final CDOAdapterPolicy[] ADAPTER_POLICIES = new CDOAdapterPolicy[0];
+
+  private static final CDORevisionPrefetchingPolicy REVISION_PREFETCHING = CDOUtil
+      .createRevisionPrefetchingPolicy(NO_REVISION_PREFETCHING);
+
+  private InternalCDOSession session;
+
+  private CDORevisionProvider revisionProvider;
+
+  public ServerCDOView(InternalSession session, CDOBranchPoint branchPoint, boolean legacyModeEnabled,
+      CDORevisionProvider revisionProvider)
+  {
+    super(branchPoint, legacyModeEnabled);
+    this.session = new ServerCDOSession(session);
+    this.revisionProvider = revisionProvider;
+
+    setViewSet(SessionUtil.prepareResourceSet(new ResourceSetImpl()));
+    setObjects(new ReferenceValueMap.Weak<CDOID, InternalCDOObject>());
+    activate();
+  }
+
+  public int getViewID()
+  {
+    return 1;
+  }
+
+  public InternalCDOSession getSession()
+  {
+    return session;
+  }
+
+  public long getLastUpdateTime()
+  {
+    return getTimeStamp();
+  }
+
+  public void setLastUpdateTime(long lastUpdateTime)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public Options options()
+  {
+    return this;
+  }
+
+  public synchronized InternalCDORevision getRevision(CDOID id, boolean loadOnDemand)
+  {
+    return (InternalCDORevision)revisionProvider.getRevision(id);
+  }
+
+  @Override
+  protected synchronized void excludeNewObject(CDOID id)
+  {
+    // Do nothing
+  }
+
+  public boolean isInvalidationRunnerActive()
+  {
+    return false;
+  }
+
+  public boolean setBranchPoint(CDOBranchPoint branchPoint)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public void lockObjects(Collection<? extends CDOObject> objects, LockType lockType, long timeout)
+      throws InterruptedException
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public void unlockObjects(Collection<? extends CDOObject> objects, LockType lockType)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public void unlockObjects()
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean waitForUpdate(long updateTime, long timeoutMillis)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public void setViewID(int viewId)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public void setSession(InternalCDOSession session)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public String getDurableLockingID()
+  {
+    return null;
+  }
+
+  public String enableDurableLocking(boolean enable)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public CDOFeatureAnalyzer getFeatureAnalyzer()
+  {
+    return CDOFeatureAnalyzer.NOOP;
+  }
+
+  public void setFeatureAnalyzer(CDOFeatureAnalyzer featureAnalyzer)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public InternalCDOTransaction toTransaction()
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public void invalidate(CDOBranch branch, long lastUpdateTime, List<CDORevisionKey> allChangedObjects,
+      List<CDOIDAndVersion> allDetachedObjects, Map<CDOID, InternalCDORevision> oldRevisions, boolean async)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public void handleLockNotification(InternalCDOView sender, CDOLockChangeInfo lockChangeInfo)
+  {
+    // Do nothing
+  }
+
+  public void prefetchRevisions(CDOID id, int depth)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean isObjectLocked(CDOObject object, LockType lockType, boolean byOthers)
+  {
+    return false;
+  }
+
+  public void handleAddAdapter(InternalCDOObject eObject, Adapter adapter)
+  {
+    // Do nothing
+  }
+
+  public void handleRemoveAdapter(InternalCDOObject eObject, Adapter adapter)
+  {
+    // Do nothing
+  }
+
+  public void subscribe(EObject eObject, Adapter adapter)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public void unsubscribe(EObject eObject, Adapter adapter)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean hasSubscription(CDOID id)
+  {
+    return false;
+  }
+
+  public CDOView getContainer()
+  {
+    return this;
+  }
+
+  public ReferenceType getCacheReferenceType()
+  {
+    return ReferenceType.WEAK;
+  }
+
+  public boolean setCacheReferenceType(ReferenceType referenceType)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public CDOInvalidationPolicy getInvalidationPolicy()
+  {
+    return CDOInvalidationPolicy.DEFAULT;
+  }
+
+  public void setInvalidationPolicy(CDOInvalidationPolicy policy)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean isInvalidationNotificationEnabled()
+  {
+    return false;
+  }
+
+  public void setInvalidationNotificationEnabled(boolean enabled)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean isLockNotificationEnabled()
+  {
+    return false;
+  }
+
+  public void setLockNotificationEnabled(boolean enabled)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public CDOAdapterPolicy[] getChangeSubscriptionPolicies()
+  {
+    return ADAPTER_POLICIES;
+  }
+
+  public void addChangeSubscriptionPolicy(CDOAdapterPolicy policy)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public void removeChangeSubscriptionPolicy(CDOAdapterPolicy policy)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public CDOAdapterPolicy getStrongReferencePolicy()
+  {
+    return CDOAdapterPolicy.ALL;
+  }
+
+  public void setStrongReferencePolicy(CDOAdapterPolicy policy)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  @Deprecated
+  public CDOStaleReferencePolicy getStaleReferenceBehaviour()
+  {
+    return getStaleReferencePolicy();
+  }
+
+  @Deprecated
+  public void setStaleReferenceBehaviour(CDOStaleReferencePolicy policy)
+  {
+    setStaleReferencePolicy(policy);
+  }
+
+  public CDOStaleReferencePolicy getStaleReferencePolicy()
+  {
+    return CDOStaleReferencePolicy.EXCEPTION;
+  }
+
+  public void setStaleReferencePolicy(CDOStaleReferencePolicy policy)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public CDORevisionPrefetchingPolicy getRevisionPrefetchingPolicy()
+  {
+    return REVISION_PREFETCHING;
+  }
+
+  public void setRevisionPrefetchingPolicy(CDORevisionPrefetchingPolicy prefetchingPolicy)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public CDOLockState[] getLockStates(Collection<CDOID> ids)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  private final class ServerCDOSession implements InternalCDOSession, CDORepositoryInfo
+  {
+    private InternalSession internalSession;
+
+    private InternalRepository repository;
+
+    public ServerCDOSession(InternalSession internalSession)
+    {
+      this.internalSession = internalSession;
+      repository = internalSession.getManager().getRepository();
+    }
+
+    public CDOView[] getElements()
+    {
+      return new ServerCDOView[] { ServerCDOView.this };
+    }
+
+    public InternalCDOTransaction getTransaction(int viewID)
+    {
+      return null;
+    }
+
+    public InternalCDOTransaction[] getTransactions()
+    {
+      return new InternalCDOTransaction[0];
+    }
+
+    public CDOView[] getViews()
+    {
+      return getElements();
+    }
+
+    public CDOView getView(int viewID)
+    {
+      return viewID == getViewID() ? ServerCDOView.this : null;
+    }
+
+    public CDOSessionProtocol getSessionProtocol()
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public CDOLobStore getLobStore()
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public InternalCDORevisionManager getRevisionManager()
+    {
+      return repository.getRevisionManager();
+    }
+
+    public InternalCDOPackageRegistry getPackageRegistry()
+    {
+      if (revisionProvider instanceof IStoreAccessor.CommitContext)
+      {
+        IStoreAccessor.CommitContext context = (IStoreAccessor.CommitContext)revisionProvider;
+        return context.getPackageRegistry();
+      }
+
+      return repository.getPackageRegistry(false);
+    }
+
+    public InternalCDOCommitInfoManager getCommitInfoManager()
+    {
+      return repository.getCommitInfoManager();
+    }
+
+    public InternalCDOBranchManager getBranchManager()
+    {
+      return repository.getBranchManager();
+    }
+
+    public void setMainBranchLocal(boolean mainBranchLocal)
+    {
+      // Do nothing
+    }
+
+    public boolean hasListeners()
+    {
+      return false;
+    }
+
+    public IListener[] getListeners()
+    {
+      return null;
+    }
+
+    public void addListener(IListener listener)
+    {
+      // Do nothing
+    }
+
+    public void removeListener(IListener listener)
+    {
+      // Do nothing
+    }
+
+    public void activate() throws LifecycleException
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public Exception deactivate()
+    {
+      return ServerCDOView.this.deactivate();
+    }
+
+    public LifecycleState getLifecycleState()
+    {
+      return LifecycleState.ACTIVE;
+    }
+
+    public boolean isActive()
+    {
+      return ServerCDOView.this.isActive();
+    }
+
+    public boolean isClosed()
+    {
+      return !isActive();
+    }
+
+    public void close()
+    {
+      deactivate();
+    }
+
+    public CDORepositoryInfo getRepositoryInfo()
+    {
+      return this;
+    }
+
+    public String getName()
+    {
+      return repository.getName();
+    }
+
+    public String getUUID()
+    {
+      return repository.getUUID();
+    }
+
+    public Type getType()
+    {
+      return repository.getType();
+    }
+
+    public State getState()
+    {
+      return repository.getState();
+    }
+
+    public long getCreationTime()
+    {
+      return repository.getCreationTime();
+    }
+
+    public long getTimeStamp()
+    {
+      return repository.getTimeStamp();
+    }
+
+    public long getTimeStamp(boolean forceRefresh)
+    {
+      return getTimeStamp();
+    }
+
+    public String getStoreType()
+    {
+      return repository.getStoreType();
+    }
+
+    public Set<ObjectType> getObjectIDTypes()
+    {
+      return repository.getObjectIDTypes();
+    }
+
+    public CDOID getRootResourceID()
+    {
+      return repository.getRootResourceID();
+    }
+
+    public boolean isSupportingAudits()
+    {
+      return repository.isSupportingAudits();
+    }
+
+    public boolean isSupportingBranches()
+    {
+      return repository.isSupportingBranches();
+    }
+
+    public boolean isSupportingEcore()
+    {
+      return repository.isSupportingEcore();
+    }
+
+    public boolean isEnsuringReferentialIntegrity()
+    {
+      return repository.isEnsuringReferentialIntegrity();
+    }
+
+    public IDGenerationLocation getIDGenerationLocation()
+    {
+      return repository.getIDGenerationLocation();
+    }
+
+    public void handleRepositoryTypeChanged(Type oldType, Type newType)
+    {
+    }
+
+    public void handleRepositoryStateChanged(State oldState, State newState)
+    {
+    }
+
+    public EPackage[] loadPackages(CDOPackageUnit packageUnit)
+    {
+      return null;
+    }
+
+    public void releaseAtomicRequestLock(Object key)
+    {
+      // Do nothing
+    }
+
+    public void acquireAtomicRequestLock(Object key)
+    {
+      // Do nothing
+    }
+
+    public Object processPackage(Object value)
+    {
+      return value;
+    }
+
+    public boolean isEmpty()
+    {
+      return false;
+    }
+
+    public boolean waitForUpdate(long updateTime, long timeoutMillis)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public void waitForUpdate(long updateTime)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public long getLastUpdateTime()
+    {
+      return getBranchPoint().getTimeStamp();
+    }
+
+    public String getUserID()
+    {
+      return null;
+    }
+
+    public int getSessionID()
+    {
+      return internalSession.getSessionID();
+    }
+
+    public long refresh()
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public Options options()
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public CDOView openView(String durableLockingID)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public CDOView openView(String durableLockingID, ResourceSet resourceSet)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public CDOView openView()
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public CDOView openView(ResourceSet resourceSet)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public CDOView openView(long timeStamp)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public CDOView openView(CDOBranch branch)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public CDOView openView(CDOBranch branch, long timeStamp)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public CDOView openView(CDOBranch branch, long timeStamp, ResourceSet resourceSet)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public CDOTransaction openTransaction(CDOBranchPoint target, ResourceSet resourceSet)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public CDOTransaction openTransaction(CDOBranchPoint target)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public CDOView openView(CDOBranchPoint target, ResourceSet resourceSet)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public CDOView openView(CDOBranchPoint target)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public CDOTransaction openTransaction(String durableLockingID)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public CDOTransaction openTransaction(String durableLockingID, ResourceSet resourceSet)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public CDOTransaction openTransaction()
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public CDOTransaction openTransaction(CDOBranch branch)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public CDOTransaction openTransaction(ResourceSet resourceSet)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public CDOTransaction openTransaction(CDOBranch branch, ResourceSet resourceSet)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public CDOFetchRuleManager getFetchRuleManager()
+    {
+      return null;
+    }
+
+    public ExceptionHandler getExceptionHandler()
+    {
+      return null;
+    }
+
+    public CDOIDGenerator getIDGenerator()
+    {
+      return null;
+    }
+
+    public void viewDetached(InternalCDOView view)
+    {
+      // Do nothing
+    }
+
+    public void setUserID(String userID)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public void setSessionProtocol(CDOSessionProtocol sessionProtocol)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public void setSessionID(int sessionID)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public void setRepositoryInfo(CDORepositoryInfo repositoryInfo)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public void setRemoteSessionManager(InternalCDORemoteSessionManager remoteSessionManager)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public void setLastUpdateTime(long lastUpdateTime)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public void setFetchRuleManager(CDOFetchRuleManager fetchRuleManager)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public void setExceptionHandler(ExceptionHandler exceptionHandler)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public void setIDGenerator(CDOIDGenerator idGenerator)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public Object resolveElementProxy(CDORevision revision, EStructuralFeature feature, int accessIndex, int serverIndex)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public void resolveAllElementProxies(CDORevision revision)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public void processRefreshSessionResult(RefreshSessionResult result, CDOBranch branch,
+        List<InternalCDOView> branchViews, Map<CDOBranch, Map<CDOID, InternalCDORevision>> viewedRevisions)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public void invalidate(CDOCommitInfo commitInfo, InternalCDOTransaction sender)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public void handleCommitNotification(CDOCommitInfo commitInfo)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public void handleLockNotification(CDOLockChangeInfo lockChangeInfo, InternalCDOView sender)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public void handleBranchNotification(InternalCDOBranch branch)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public InternalCDORemoteSessionManager getRemoteSessionManager()
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public CDOAuthenticator getAuthenticator()
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public void setAuthenticator(CDOAuthenticator authenticator)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public void setRevisionManager(InternalCDORevisionManager revisionManager)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public void setBranchManager(InternalCDOBranchManager branchManager)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public void setCommitInfoManager(InternalCDOCommitInfoManager commitInfoManager)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public void setPackageRegistry(InternalCDOPackageRegistry packageRegistry)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public boolean isSticky()
+    {
+      return false;
+    }
+
+    public CDOBranchPoint getCommittedSinceLastRefresh(CDOID id)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public void setCommittedSinceLastRefresh(CDOID id, CDOBranchPoint branchPoint)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public void clearCommittedSinceLastRefresh()
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public CDOChangeSetData compareRevisions(CDOBranchPoint source, CDOBranchPoint target)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public CDORevisionAvailabilityInfo createRevisionAvailabilityInfo(CDOBranchPoint branchPoint)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public void cacheRevisions(CDORevisionAvailabilityInfo info)
+    {
+      throw new UnsupportedOperationException();
+    }
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Session.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Session.java
new file mode 100644
index 0000000..bb0205d
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Session.java
@@ -0,0 +1,574 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Simon McDuff - bug 201266
+ *    Simon McDuff - bug 230832
+ *    Simon McDuff - bug 233490
+ *    Simon McDuff - bug 213402
+ */
+package org.eclipse.emf.cdo.internal.server;
+
+import org.eclipse.emf.cdo.common.CDOCommonRepository;
+import org.eclipse.emf.cdo.common.CDOCommonSession;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.id.CDOIDUtil;
+import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
+import org.eclipse.emf.cdo.common.model.CDOModelUtil;
+import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants;
+import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionKey;
+import org.eclipse.emf.cdo.common.revision.CDORevisionUtil;
+import org.eclipse.emf.cdo.internal.common.commit.DelegatingCommitInfo;
+import org.eclipse.emf.cdo.server.IView;
+import org.eclipse.emf.cdo.session.remote.CDORemoteSessionMessage;
+import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranch;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager;
+import org.eclipse.emf.cdo.spi.server.ISessionProtocol;
+import org.eclipse.emf.cdo.spi.server.InternalSession;
+import org.eclipse.emf.cdo.spi.server.InternalSessionManager;
+import org.eclipse.emf.cdo.spi.server.InternalTransaction;
+import org.eclipse.emf.cdo.spi.server.InternalView;
+
+import org.eclipse.net4j.util.ReflectUtil.ExcludeFromDump;
+import org.eclipse.net4j.util.collection.IndexedList;
+import org.eclipse.net4j.util.container.Container;
+import org.eclipse.net4j.util.event.EventUtil;
+import org.eclipse.net4j.util.event.IListener;
+import org.eclipse.net4j.util.lifecycle.ILifecycle;
+import org.eclipse.net4j.util.lifecycle.LifecycleEventAdapter;
+import org.eclipse.net4j.util.lifecycle.LifecycleUtil;
+import org.eclipse.net4j.util.om.log.OMLogger;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+import java.text.MessageFormat;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * @author Eike Stepper
+ */
+public class Session extends Container<IView> implements InternalSession
+{
+  private InternalSessionManager manager;
+
+  private ISessionProtocol protocol;
+
+  private int sessionID;
+
+  private String userID;
+
+  private boolean passiveUpdateEnabled = true;
+
+  private PassiveUpdateMode passiveUpdateMode = PassiveUpdateMode.INVALIDATIONS;
+
+  private LockNotificationMode lockNotificationMode = LockNotificationMode.IF_REQUIRED_BY_VIEWS;
+
+  private long lastUpdateTime;
+
+  @ExcludeFromDump
+  private Object lastUpdateTimeLock = new Object();
+
+  private ConcurrentMap<Integer, InternalView> views = new ConcurrentHashMap<Integer, InternalView>();
+
+  private AtomicInteger lastTempViewID = new AtomicInteger();
+
+  @ExcludeFromDump
+  private IListener protocolListener = new LifecycleEventAdapter()
+  {
+    @Override
+    protected void onDeactivated(ILifecycle lifecycle)
+    {
+      deactivate();
+    }
+  };
+
+  private boolean subscribed;
+
+  /**
+   * @since 2.0
+   */
+  public Session(InternalSessionManager manager, ISessionProtocol protocol, int sessionID, String userID)
+  {
+    this.manager = manager;
+    this.protocol = protocol;
+    this.sessionID = sessionID;
+    this.userID = userID;
+
+    EventUtil.addListener(protocol, protocolListener);
+    activate();
+  }
+
+  /**
+   * @since 2.0
+   */
+  public Options options()
+  {
+    return this;
+  }
+
+  /**
+   * @since 2.0
+   */
+  public CDOCommonSession getContainer()
+  {
+    return this;
+  }
+
+  public InternalSessionManager getManager()
+  {
+    return manager;
+  }
+
+  public ISessionProtocol getProtocol()
+  {
+    return protocol;
+  }
+
+  public int getSessionID()
+  {
+    return sessionID;
+  }
+
+  /**
+   * @since 2.0
+   */
+  public String getUserID()
+  {
+    return userID;
+  }
+
+  /**
+   * @since 2.0
+   */
+  public boolean isSubscribed()
+  {
+    return subscribed;
+  }
+
+  /**
+   * @since 2.0
+   */
+  public void setSubscribed(boolean subscribed)
+  {
+    checkActive();
+    if (this.subscribed != subscribed)
+    {
+      this.subscribed = subscribed;
+      byte opcode = subscribed ? CDOProtocolConstants.REMOTE_SESSION_SUBSCRIBED
+          : CDOProtocolConstants.REMOTE_SESSION_UNSUBSCRIBED;
+      manager.sendRemoteSessionNotification(this, opcode);
+    }
+  }
+
+  /**
+   * @since 2.0
+   */
+  public boolean isPassiveUpdateEnabled()
+  {
+    return passiveUpdateEnabled;
+  }
+
+  /**
+   * @since 2.0
+   */
+  public void setPassiveUpdateEnabled(boolean passiveUpdateEnabled)
+  {
+    checkActive();
+    this.passiveUpdateEnabled = passiveUpdateEnabled;
+  }
+
+  public PassiveUpdateMode getPassiveUpdateMode()
+  {
+    return passiveUpdateMode;
+  }
+
+  public void setPassiveUpdateMode(PassiveUpdateMode passiveUpdateMode)
+  {
+    checkActive();
+    checkArg(passiveUpdateMode, "passiveUpdateMode");
+    this.passiveUpdateMode = passiveUpdateMode;
+  }
+
+  public LockNotificationMode getLockNotificationMode()
+  {
+    return lockNotificationMode;
+  }
+
+  public void setLockNotificationMode(LockNotificationMode lockNotificationMode)
+  {
+    checkActive();
+    checkArg(lockNotificationMode, "lockNotificationMode");
+    this.lockNotificationMode = lockNotificationMode;
+  }
+
+  public long getLastUpdateTime()
+  {
+    synchronized (lastUpdateTimeLock)
+    {
+      return lastUpdateTime;
+    }
+  }
+
+  public InternalView[] getElements()
+  {
+    checkActive();
+    return getViews();
+  }
+
+  @Override
+  public boolean isEmpty()
+  {
+    checkActive();
+    return views.isEmpty();
+  }
+
+  public InternalView[] getViews()
+  {
+    checkActive();
+    return getViewsArray();
+  }
+
+  private InternalView[] getViewsArray()
+  {
+    return views.values().toArray(new InternalView[views.size()]);
+  }
+
+  public InternalView getView(int viewID)
+  {
+    checkActive();
+    return views.get(viewID);
+  }
+
+  /**
+   * @since 2.0
+   */
+  public InternalView openView(int viewID, CDOBranchPoint branchPoint)
+  {
+    checkActive();
+    if (viewID == TEMP_VIEW_ID)
+    {
+      viewID = -lastTempViewID.incrementAndGet();
+    }
+
+    InternalView view = new View(this, viewID, branchPoint);
+    view.activate();
+    addView(view);
+    return view;
+  }
+
+  /**
+   * @since 2.0
+   */
+  public InternalTransaction openTransaction(int viewID, CDOBranchPoint branchPoint)
+  {
+    checkActive();
+    if (viewID == TEMP_VIEW_ID)
+    {
+      viewID = -lastTempViewID.incrementAndGet();
+    }
+
+    InternalTransaction transaction = new Transaction(this, viewID, branchPoint);
+    transaction.activate();
+    addView(transaction);
+    return transaction;
+  }
+
+  private void addView(InternalView view)
+  {
+    checkActive();
+    int viewID = view.getViewID();
+    views.put(viewID, view);
+    fireElementAddedEvent(view);
+  }
+
+  /**
+   * @since 2.0
+   */
+  public void viewClosed(InternalView view)
+  {
+    int viewID = view.getViewID();
+    if (views.remove(viewID) == view)
+    {
+      view.doClose();
+      fireElementRemovedEvent(view);
+    }
+  }
+
+  /**
+   * TODO I can't see how recursion is controlled/limited
+   * 
+   * @since 2.0
+   */
+  public void collectContainedRevisions(InternalCDORevision revision, CDOBranchPoint branchPoint, int referenceChunk,
+      Set<CDOID> revisions, List<CDORevision> additionalRevisions)
+  {
+    InternalCDORevisionManager revisionManager = getManager().getRepository().getRevisionManager();
+    EClass eClass = revision.getEClass();
+    EStructuralFeature[] features = CDOModelUtil.getAllPersistentFeatures(eClass);
+    for (int i = 0; i < features.length; i++)
+    {
+      EStructuralFeature feature = features[i];
+      // TODO Clarify feature maps
+      if (feature instanceof EReference && !feature.isMany() && ((EReference)feature).isContainment())
+      {
+        Object value = revision.getValue(feature);
+        if (value instanceof CDOID)
+        {
+          CDOID id = (CDOID)value;
+          if (!CDOIDUtil.isNull(id) && !revisions.contains(id))
+          {
+            InternalCDORevision containedRevision = revisionManager.getRevision(id, branchPoint, referenceChunk,
+                CDORevision.DEPTH_NONE, true);
+            revisions.add(id);
+            additionalRevisions.add(containedRevision);
+
+            // Recurse
+            collectContainedRevisions(containedRevision, branchPoint, referenceChunk, revisions, additionalRevisions);
+          }
+        }
+      }
+    }
+  }
+
+  public CDOID provideCDOID(Object idObject)
+  {
+    return (CDOID)idObject;
+  }
+
+  public void sendRepositoryTypeNotification(CDOCommonRepository.Type oldType, CDOCommonRepository.Type newType)
+      throws Exception
+  {
+    if (protocol != null)
+    {
+      protocol.sendRepositoryTypeNotification(oldType, newType);
+    }
+  }
+
+  @Deprecated
+  public void sendRepositoryStateNotification(CDOCommonRepository.State oldState, CDOCommonRepository.State newState)
+      throws Exception
+  {
+    sendRepositoryStateNotification(oldState, newState, null);
+  }
+
+  public void sendRepositoryStateNotification(CDOCommonRepository.State oldState, CDOCommonRepository.State newState,
+      CDOID rootResourceID) throws Exception
+  {
+    if (protocol != null)
+    {
+      protocol.sendRepositoryStateNotification(oldState, newState, rootResourceID);
+    }
+  }
+
+  public void sendBranchNotification(InternalCDOBranch branch) throws Exception
+  {
+    if (protocol != null)
+    {
+      protocol.sendBranchNotification(branch);
+    }
+  }
+
+  public void sendCommitNotification(final CDOCommitInfo commitInfo) throws Exception
+  {
+    if (protocol == null)
+    {
+      return;
+    }
+
+    if (!isPassiveUpdateEnabled())
+    {
+      return;
+    }
+
+    final InternalView[] views = getViews();
+    protocol.sendCommitNotification(new DelegatingCommitInfo()
+    {
+      private final PassiveUpdateMode passiveUpdateMode = getPassiveUpdateMode();
+
+      private final boolean additions = passiveUpdateMode == PassiveUpdateMode.ADDITIONS;
+
+      private final boolean changes = passiveUpdateMode == PassiveUpdateMode.CHANGES;
+
+      @Override
+      protected CDOCommitInfo getDelegate()
+      {
+        return commitInfo;
+      }
+
+      @Override
+      public List<CDOIDAndVersion> getNewObjects()
+      {
+        final List<CDOIDAndVersion> newObjects = super.getNewObjects();
+        return new IndexedList<CDOIDAndVersion>()
+        {
+          @Override
+          public CDOIDAndVersion get(int index)
+          {
+            // The following will always be a CDORevision!
+            CDOIDAndVersion newObject = newObjects.get(index);
+            if (additions)
+            {
+              // Return full revisions if not in INVALIDATION mode
+              return newObject;
+            }
+
+            // Prevent sending whole revisions by copying the id and version
+            return CDOIDUtil.createIDAndVersion(newObject);
+          }
+
+          @Override
+          public int size()
+          {
+            return newObjects.size();
+          }
+        };
+      }
+
+      @Override
+      public List<CDORevisionKey> getChangedObjects()
+      {
+        final List<CDORevisionKey> changedObjects = super.getChangedObjects();
+        return new IndexedList<CDORevisionKey>()
+        {
+          @Override
+          public CDORevisionKey get(int index)
+          {
+            // The following will always be a CDORevisionDelta!
+            CDORevisionKey changedObject = changedObjects.get(index);
+            if (changes || additions || hasSubscription(changedObject.getID(), views))
+            {
+              return changedObject;
+            }
+
+            // Prevent sending whole revisions by copying the id and version
+            return CDORevisionUtil.copyRevisionKey(changedObject);
+          }
+
+          @Override
+          public int size()
+          {
+            return changedObjects.size();
+          }
+        };
+      }
+    });
+
+    synchronized (lastUpdateTimeLock)
+    {
+      lastUpdateTime = commitInfo.getTimeStamp();
+    }
+  }
+
+  public void sendLockNotification(CDOLockChangeInfo lockChangeInfo) throws Exception
+  {
+    if (protocol != null)
+    {
+      if (options().getLockNotificationMode() == LockNotificationMode.ALWAYS)
+      {
+        protocol.sendLockNotification(lockChangeInfo);
+        return;
+      }
+
+      if (options().getLockNotificationMode() == LockNotificationMode.IF_REQUIRED_BY_VIEWS)
+      {
+        // If this session has one (or more) views configured for this branch,
+        // only then do we send the lockChangeInfo.
+        for (InternalView view : getViews())
+        {
+          if (view.options().isLockNotificationEnabled() && view.getBranch().equals(lockChangeInfo.getBranch()))
+          {
+            protocol.sendLockNotification(lockChangeInfo);
+            break;
+          }
+        }
+      }
+    }
+  }
+
+  private boolean hasSubscription(CDOID id, InternalView[] views)
+  {
+    for (InternalView view : views)
+    {
+      if (view.hasSubscription(id))
+      {
+        return true;
+      }
+    }
+
+    return false;
+  }
+
+  public void sendRemoteSessionNotification(InternalSession sender, byte opcode) throws Exception
+  {
+    if (protocol != null)
+    {
+      protocol.sendRemoteSessionNotification(sender, opcode);
+    }
+  }
+
+  public void sendRemoteMessageNotification(InternalSession sender, CDORemoteSessionMessage message) throws Exception
+  {
+    if (protocol != null)
+    {
+      protocol.sendRemoteMessageNotification(sender, message);
+    }
+  }
+
+  @Override
+  public String toString()
+  {
+    return MessageFormat.format("Session[{0}]", sessionID); //$NON-NLS-1$
+  }
+
+  /**
+   * @since 2.0
+   */
+  public void close()
+  {
+    LifecycleUtil.deactivate(this, OMLogger.Level.DEBUG);
+  }
+
+  /**
+   * @since 2.0
+   */
+  public boolean isClosed()
+  {
+    return !isActive();
+  }
+
+  @Override
+  protected void doDeactivate() throws Exception
+  {
+    EventUtil.removeListener(protocol, protocolListener);
+    protocolListener = null;
+
+    LifecycleUtil.deactivate(protocol, OMLogger.Level.DEBUG);
+    protocol = null;
+
+    for (IView view : getViewsArray())
+    {
+      view.close();
+    }
+
+    views = null;
+    manager.sessionClosed(this);
+    manager = null;
+    super.doDeactivate();
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/SessionManager.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/SessionManager.java
new file mode 100644
index 0000000..22f71b8
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/SessionManager.java
@@ -0,0 +1,482 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Simon McDuff - bug 201266
+ *    Simon McDuff - bug 202725
+ */
+package org.eclipse.emf.cdo.internal.server;
+
+import org.eclipse.emf.cdo.common.CDOCommonRepository;
+import org.eclipse.emf.cdo.common.CDOCommonSession.Options.LockNotificationMode;
+import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
+import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants;
+import org.eclipse.emf.cdo.internal.server.bundle.OM;
+import org.eclipse.emf.cdo.server.ISession;
+import org.eclipse.emf.cdo.session.remote.CDORemoteSessionMessage;
+import org.eclipse.emf.cdo.spi.common.CDOAuthenticationResult;
+import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranch;
+import org.eclipse.emf.cdo.spi.server.ISessionProtocol;
+import org.eclipse.emf.cdo.spi.server.InternalRepository;
+import org.eclipse.emf.cdo.spi.server.InternalSession;
+import org.eclipse.emf.cdo.spi.server.InternalSessionManager;
+
+import org.eclipse.net4j.util.ReflectUtil.ExcludeFromDump;
+import org.eclipse.net4j.util.container.Container;
+import org.eclipse.net4j.util.lifecycle.LifecycleUtil;
+import org.eclipse.net4j.util.om.trace.ContextTracer;
+import org.eclipse.net4j.util.security.IRandomizer;
+import org.eclipse.net4j.util.security.IUserManager;
+import org.eclipse.net4j.util.security.NegotiationException;
+import org.eclipse.net4j.util.security.Randomizer;
+import org.eclipse.net4j.util.security.SecurityUtil;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * @author Eike Stepper
+ */
+public class SessionManager extends Container<ISession> implements InternalSessionManager
+{
+  public static final int DEFAULT_TOKEN_LENGTH = 1024;
+
+  private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_SESSION, SessionManager.class);
+
+  private InternalRepository repository;
+
+  @ExcludeFromDump
+  private String encryptionAlgorithmName = SecurityUtil.PBE_WITH_MD5_AND_DES;
+
+  @ExcludeFromDump
+  private byte[] encryptionSaltBytes = SecurityUtil.DEFAULT_SALT;
+
+  @ExcludeFromDump
+  private int encryptionIterationCount = SecurityUtil.DEFAULT_ITERATION_COUNT;
+
+  private int tokenLength = DEFAULT_TOKEN_LENGTH;
+
+  private IRandomizer randomizer;
+
+  private IUserManager userManager;
+
+  private final Map<Integer, InternalSession> sessions = new HashMap<Integer, InternalSession>();
+
+  private final AtomicInteger lastSessionID = new AtomicInteger();
+
+  /**
+   * @since 2.0
+   */
+  public SessionManager()
+  {
+  }
+
+  /**
+   * @since 2.0
+   */
+  public InternalRepository getRepository()
+  {
+    return repository;
+  }
+
+  /**
+   * @since 2.0
+   */
+  public void setRepository(InternalRepository repository)
+  {
+    checkInactive();
+    this.repository = repository;
+  }
+
+  public String getEncryptionAlgorithmName()
+  {
+    return encryptionAlgorithmName;
+  }
+
+  public void setEncryptionAlgorithmName(String encryptionAlgorithmName)
+  {
+    checkInactive();
+    this.encryptionAlgorithmName = encryptionAlgorithmName;
+  }
+
+  public byte[] getEncryptionSaltBytes()
+  {
+    return encryptionSaltBytes;
+  }
+
+  public void setEncryptionSaltBytes(byte[] encryptionSaltBytes)
+  {
+    checkInactive();
+    this.encryptionSaltBytes = encryptionSaltBytes;
+  }
+
+  public int getEncryptionIterationCount()
+  {
+    return encryptionIterationCount;
+  }
+
+  public void setEncryptionIterationCount(int encryptionIterationCount)
+  {
+    checkInactive();
+    this.encryptionIterationCount = encryptionIterationCount;
+  }
+
+  public int getTokenLength()
+  {
+    return tokenLength;
+  }
+
+  public void setTokenLength(int tokenLength)
+  {
+    checkInactive();
+    this.tokenLength = tokenLength;
+  }
+
+  public IRandomizer getRandomizer()
+  {
+    return randomizer;
+  }
+
+  public void setRandomizer(IRandomizer randomizer)
+  {
+    checkInactive();
+    this.randomizer = randomizer;
+  }
+
+  public IUserManager getUserManager()
+  {
+    return userManager;
+  }
+
+  public void setUserManager(IUserManager userManager)
+  {
+    this.userManager = userManager;
+  }
+
+  public InternalSession[] getSessions()
+  {
+    synchronized (sessions)
+    {
+      return sessions.values().toArray(new InternalSession[sessions.size()]);
+    }
+  }
+
+  /**
+   * @since 2.0
+   */
+  public InternalSession getSession(int sessionID)
+  {
+    checkActive();
+    synchronized (sessions)
+    {
+      return sessions.get(sessionID);
+    }
+  }
+
+  public InternalSession[] getElements()
+  {
+    return getSessions();
+  }
+
+  @Override
+  public boolean isEmpty()
+  {
+    synchronized (sessions)
+    {
+      return sessions.isEmpty();
+    }
+  }
+
+  /**
+   * @since 2.0
+   */
+  public InternalSession openSession(ISessionProtocol sessionProtocol)
+  {
+    int id = lastSessionID.incrementAndGet();
+    if (TRACER.isEnabled())
+    {
+      TRACER.trace("Opening session " + id); //$NON-NLS-1$
+    }
+
+    String userID = authenticateUser(sessionProtocol);
+    InternalSession session = createSession(id, userID, sessionProtocol);
+    LifecycleUtil.activate(session);
+
+    synchronized (sessions)
+    {
+      sessions.put(id, session);
+    }
+
+    fireElementAddedEvent(session);
+    sendRemoteSessionNotification(session, CDOProtocolConstants.REMOTE_SESSION_OPENED);
+    return session;
+  }
+
+  protected InternalSession createSession(int id, String userID, ISessionProtocol protocol)
+  {
+    return new Session(this, protocol, id, userID);
+  }
+
+  public void sessionClosed(InternalSession session)
+  {
+    int sessionID = session.getSessionID();
+    InternalSession removeSession = null;
+    synchronized (sessions)
+    {
+      removeSession = sessions.remove(sessionID);
+    }
+
+    if (removeSession != null)
+    {
+      fireElementRemovedEvent(session);
+      sendRemoteSessionNotification(session, CDOProtocolConstants.REMOTE_SESSION_CLOSED);
+    }
+  }
+
+  public void sendRepositoryTypeNotification(CDOCommonRepository.Type oldType, CDOCommonRepository.Type newType)
+  {
+    for (InternalSession session : getSessions())
+    {
+      try
+      {
+        session.sendRepositoryTypeNotification(oldType, newType);
+      }
+      catch (Exception ex)
+      {
+        handleNotificationProblem(session, ex);
+      }
+    }
+  }
+
+  @Deprecated
+  public void sendRepositoryStateNotification(CDOCommonRepository.State oldState, CDOCommonRepository.State newState)
+  {
+    sendRepositoryStateNotification(oldState, newState, null);
+  }
+
+  public void sendRepositoryStateNotification(CDOCommonRepository.State oldState, CDOCommonRepository.State newState,
+      CDOID rootResourceID)
+  {
+    for (InternalSession session : getSessions())
+    {
+      try
+      {
+        session.sendRepositoryStateNotification(oldState, newState, rootResourceID);
+      }
+      catch (Exception ex)
+      {
+        handleNotificationProblem(session, ex);
+      }
+    }
+  }
+
+  public void sendBranchNotification(InternalSession sender, InternalCDOBranch branch)
+  {
+    for (InternalSession session : getSessions())
+    {
+      if (session != sender)
+      {
+        try
+        {
+          session.sendBranchNotification(branch);
+        }
+        catch (Exception ex)
+        {
+          handleNotificationProblem(session, ex);
+        }
+      }
+    }
+  }
+
+  public void sendCommitNotification(InternalSession sender, CDOCommitInfo commitInfo)
+  {
+    for (InternalSession session : getSessions())
+    {
+      if (session != sender)
+      {
+        try
+        {
+          session.sendCommitNotification(commitInfo);
+        }
+        catch (Exception ex)
+        {
+          handleNotificationProblem(session, ex);
+        }
+      }
+    }
+  }
+
+  public void sendLockNotification(InternalSession sender, CDOLockChangeInfo lockChangeInfo)
+  {
+    for (InternalSession session : getSessions())
+    {
+      if (session == sender || session.options().getLockNotificationMode() == LockNotificationMode.OFF)
+      {
+        continue;
+      }
+
+      try
+      {
+        session.sendLockNotification(lockChangeInfo);
+      }
+      catch (Exception ex)
+      {
+        handleNotificationProblem(session, ex);
+      }
+    }
+  }
+
+  /**
+   * @since 2.0
+   */
+  public void sendRemoteSessionNotification(InternalSession sender, byte opcode)
+  {
+    try
+    {
+      for (InternalSession session : getSessions())
+      {
+        if (session != sender && session.isSubscribed())
+        {
+          try
+          {
+            session.sendRemoteSessionNotification(sender, opcode);
+          }
+          catch (Exception ex)
+          {
+            handleNotificationProblem(session, ex);
+          }
+        }
+      }
+    }
+    catch (Exception ex)
+    {
+      OM.LOG.warn("A problem occured while notifying other sessions", ex);
+    }
+  }
+
+  public List<Integer> sendRemoteMessageNotification(InternalSession sender, CDORemoteSessionMessage message,
+      int[] recipients)
+  {
+    List<Integer> result = new ArrayList<Integer>();
+    for (int i = 0; i < recipients.length; i++)
+    {
+      InternalSession recipient = getSession(recipients[i]);
+
+      try
+      {
+        if (recipient != null && recipient.isSubscribed())
+        {
+          recipient.sendRemoteMessageNotification(sender, message);
+          result.add(recipient.getSessionID());
+        }
+      }
+      catch (Exception ex)
+      {
+        handleNotificationProblem(recipient, ex);
+      }
+    }
+
+    return result;
+  }
+
+  protected void handleNotificationProblem(InternalSession session, Throwable t)
+  {
+    OM.LOG.warn("A problem occured while notifying session " + session, t);
+  }
+
+  protected String authenticateUser(ISessionProtocol protocol) throws SecurityException
+  {
+    if (protocol == null)
+    {
+      return null;
+    }
+
+    if (userManager == null)
+    {
+      return null;
+    }
+
+    try
+    {
+      byte[] randomToken = createRandomToken();
+      CDOAuthenticationResult result = protocol.sendAuthenticationChallenge(randomToken);
+      String userID = result.getUserID();
+
+      byte[] cryptedToken = encryptToken(userID, randomToken);
+      boolean success = Arrays.equals(result.getCryptedToken(), cryptedToken);
+      if (success)
+      {
+        return userID;
+      }
+
+      throw new SecurityException("User not authenticated"); //$NON-NLS-1$
+    }
+    catch (SecurityException ex)
+    {
+      throw ex;
+    }
+    catch (Exception ex)
+    {
+      throw new SecurityException(ex);
+    }
+  }
+
+  protected byte[] createRandomToken()
+  {
+    byte[] token = new byte[tokenLength];
+    randomizer.nextBytes(token);
+    return token;
+  }
+
+  protected byte[] encryptToken(String userID, byte[] token) throws NegotiationException
+  {
+    try
+    {
+      return userManager.encrypt(userID, token, getEncryptionAlgorithmName(), getEncryptionSaltBytes(),
+          getEncryptionIterationCount());
+    }
+    catch (Exception ex)
+    {
+      OM.LOG.error("Token encryption failed", ex); //$NON-NLS-1$
+      return null;
+    }
+  }
+
+  @Override
+  protected void doActivate() throws Exception
+  {
+    super.doActivate();
+    if (userManager != null)
+    {
+      if (randomizer == null)
+      {
+        randomizer = new Randomizer();
+      }
+
+      LifecycleUtil.activate(randomizer);
+    }
+  }
+
+  @Override
+  protected void doDeactivate() throws Exception
+  {
+    InternalSession[] activeSessions = getSessions();
+    for (int i = 0; i < activeSessions.length; i++)
+    {
+      LifecycleUtil.deactivate(activeSessions[i]);
+    }
+
+    super.doDeactivate();
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/TimeStampAuthority.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/TimeStampAuthority.java
new file mode 100644
index 0000000..eebbbfb
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/TimeStampAuthority.java
@@ -0,0 +1,230 @@
+/**
+ * Copyright (c) 2004 - 2009 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *    Caspar De Groot - initial API and implementation
+ */
+package org.eclipse.emf.cdo.internal.server;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.spi.server.InternalRepository;
+
+import org.eclipse.net4j.util.ReflectUtil.ExcludeFromDump;
+import org.eclipse.net4j.util.concurrent.ConcurrencyUtil;
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * Bugzilla 297940, 290032
+ * 
+ * @author Caspar De Groot
+ */
+class TimeStampAuthority
+{
+  private InternalRepository repository;
+
+  /**
+   * Holds the timestamp that was issued in response to the last call to {@link #createTimestamp()}
+   */
+  @ExcludeFromDump
+  private transient long lastIssuedTimeStamp = CDOBranchPoint.UNSPECIFIED_DATE;
+
+  /**
+   * Holds the timestamp that was last reported finished by a call to {@link #endCommit(long)}
+   */
+  private long lastFinishedTimeStamp;
+
+  private LastCommitTimeStampLock lastCommitTimeStampLock = new LastCommitTimeStampLock();
+
+  private boolean strictOrdering; // TODO (CD) Should be a repo property
+
+  /**
+   * A lock to block on if strict commit ordering is enabled
+   */
+  private StrictOrderingLock strictOrderingLock = new StrictOrderingLock();
+
+  /**
+   * An ordered list of timestamps that have been issued but have not (yet) been reported finished. (It is ordered
+   * because the timestamps are added sequentially.)
+   */
+  private List<Long> runningTransactions = new LinkedList<Long>();
+
+  /**
+   * A set of timestamps that have been reported finished but have not yet been
+   */
+  private SortedSet<Long> finishedTransactions = new TreeSet<Long>();
+
+  TimeStampAuthority(InternalRepository repository)
+  {
+    this.repository = repository;
+  }
+
+  synchronized long[] startCommit(OMMonitor monitor)
+  {
+    return startCommit(CDOBranchPoint.UNSPECIFIED_DATE, monitor);
+  }
+
+  synchronized long[] startCommit(long timeStampOverride, OMMonitor monitor)
+  {
+    monitor.begin();
+
+    if (strictOrdering)
+    {
+      strictOrderingLock.lock();
+    }
+
+    try
+    {
+      long now = repository.getTimeStamp();
+      if (lastIssuedTimeStamp != CDOBranchPoint.UNSPECIFIED_DATE)
+      {
+        while (lastIssuedTimeStamp == now)
+        {
+          ConcurrencyUtil.sleep(1);
+          now = repository.getTimeStamp();
+          monitor.checkCanceled();
+        }
+      }
+
+      if (timeStampOverride != CDOBranchPoint.UNSPECIFIED_DATE)
+      {
+        now = timeStampOverride;
+      }
+
+      lastIssuedTimeStamp = now;
+
+      runningTransactions.add(lastIssuedTimeStamp);
+      return new long[] { lastIssuedTimeStamp, getLastFinishedTimeStamp() };
+    }
+    finally
+    {
+      monitor.done();
+    }
+  }
+
+  synchronized void endCommit(long timeStamp)
+  {
+    if (!runningTransactions.remove(timeStamp))
+    {
+      throw new IllegalArgumentException("Cannot end transaction with unknown timestamp " + timeStamp);
+    }
+
+    finishedTransactions.add(timeStamp);
+
+    // We can remove a timestamp from finishedTransactions if it is smaller (i.e. older) than any
+    // of the runningTransactions. Since both sets are sorted, we only need to compare the heads.
+    long oldestRunning = runningTransactions.isEmpty() ? Long.MAX_VALUE : runningTransactions.get(0);
+    long oldestFinished;
+    synchronized (lastCommitTimeStampLock)
+    {
+      long oldValue = lastFinishedTimeStamp;
+      while (!finishedTransactions.isEmpty() && (oldestFinished = finishedTransactions.first()) < oldestRunning)
+      {
+        finishedTransactions.remove(oldestFinished);
+        lastFinishedTimeStamp = oldestFinished;
+      }
+
+      // If we actually changed the lastFinishedTimeStamp, we need to notify waiting threads
+      if (lastFinishedTimeStamp != oldValue)
+      {
+        lastCommitTimeStampLock.notifyAll();
+      }
+    }
+
+    if (strictOrdering)
+    {
+      strictOrderingLock.unlock();
+    }
+  }
+
+  synchronized void failCommit(long timeStamp)
+  {
+    if (timeStamp != CDOBranchPoint.UNSPECIFIED_DATE) // Exclude problems before TransactionCommitContext.setTimeStamp()
+    {
+      if (!runningTransactions.remove(timeStamp))
+      {
+        throw new IllegalArgumentException("Cannot fail transaction with unknown timestamp " + timeStamp);
+      }
+    }
+
+    if (strictOrdering)
+    {
+      strictOrderingLock.unlock();
+    }
+  }
+
+  synchronized long getLastFinishedTimeStamp()
+  {
+    if (lastFinishedTimeStamp != 0)
+    {
+      return lastFinishedTimeStamp;
+    }
+
+    // If we get here, no commit has finished since the server was started
+    if (lastIssuedTimeStamp == 0) // No commit has started either
+    {
+      // We can safely return the current system time minus one milli.
+      return repository.getTimeStamp() - 1;
+    }
+
+    // If we get here, one or more commits are running
+    // We can safely return the start time of the longest-running, minus one milli.
+    return runningTransactions.get(0) - 1;
+  }
+
+  long waitForCommit(long timeout)
+  {
+    synchronized (lastCommitTimeStampLock)
+    {
+      try
+      {
+        lastCommitTimeStampLock.wait(timeout);
+      }
+      catch (Exception ignore)
+      {
+      }
+
+      return lastFinishedTimeStamp;
+    }
+  }
+
+  void setLastFinishedTimeStamp(long lastCommitTimeStamp)
+  {
+    synchronized (lastCommitTimeStampLock)
+    {
+      if (lastFinishedTimeStamp < lastCommitTimeStamp)
+      {
+        lastFinishedTimeStamp = lastCommitTimeStamp;
+        lastCommitTimeStampLock.notifyAll();
+      }
+    }
+  }
+
+  /**
+   * A separate class for better monitor debugging.
+   * 
+   * @author Eike Stepper
+   */
+  private static final class LastCommitTimeStampLock
+  {
+  }
+
+  /**
+   * A separate class for better monitor debugging.
+   * 
+   * @author Eike Stepper
+   */
+  private static final class StrictOrderingLock extends ReentrantLock
+  {
+    private static final long serialVersionUID = 1L;
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Transaction.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Transaction.java
new file mode 100644
index 0000000..31f7452
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Transaction.java
@@ -0,0 +1,88 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Simon McDuff - bug 233490
+ *    Simon McDuff - bug 213402
+ */
+package org.eclipse.emf.cdo.internal.server;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.spi.server.InternalCommitContext;
+import org.eclipse.emf.cdo.spi.server.InternalSession;
+import org.eclipse.emf.cdo.spi.server.InternalTransaction;
+
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+
+/**
+ * @author Eike Stepper
+ * @since 2.0
+ */
+public class Transaction extends View implements InternalTransaction
+{
+  public Transaction(InternalSession session, int viewID, CDOBranchPoint branchPoint)
+  {
+    super(session, viewID, branchPoint);
+  }
+
+  @Override
+  public boolean isReadOnly()
+  {
+    return false;
+  }
+
+  @Override
+  protected String getClassName()
+  {
+    return "Transaction"; //$NON-NLS-1$
+  }
+
+  /**
+   * @since 2.0
+   */
+  public InternalCommitContext createCommitContext()
+  {
+    checkOpen();
+    return getRepository().createCommitContext(this);
+  }
+
+  /**
+   * For tests only.
+   * 
+   * @since 2.0
+   */
+  public InternalCommitContext testCreateCommitContext(final long timeStamp)
+  {
+    checkOpen();
+    return new TransactionCommitContext(this)
+    {
+      @Override
+      protected long[] createTimeStamp(OMMonitor monitor)
+      {
+        return new long[] { timeStamp, CDOBranchPoint.UNSPECIFIED_DATE };
+      }
+    };
+  }
+
+  @Override
+  protected void validateTimeStamp(long timeStamp) throws IllegalArgumentException
+  {
+    if (timeStamp != UNSPECIFIED_DATE)
+    {
+      throw new IllegalArgumentException("Changing the target time is not supported by transactions");
+    }
+  }
+
+  private void checkOpen()
+  {
+    if (isClosed())
+    {
+      throw new IllegalStateException("View closed"); //$NON-NLS-1$
+    }
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/TransactionCommitContext.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/TransactionCommitContext.java
new file mode 100644
index 0000000..e978f5c
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/TransactionCommitContext.java
@@ -0,0 +1,1404 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Simon McDuff - initial API and implementation
+ *    Eike Stepper - maintenance
+ *    Martin Fluegge - maintenance, bug 318518
+ */
+package org.eclipse.emf.cdo.internal.server;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.commit.CDOCommitData;
+import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.id.CDOIDObject;
+import org.eclipse.emf.cdo.common.id.CDOIDReference;
+import org.eclipse.emf.cdo.common.id.CDOIDUtil;
+import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
+import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo.Operation;
+import org.eclipse.emf.cdo.common.lock.CDOLockState;
+import org.eclipse.emf.cdo.common.lock.CDOLockUtil;
+import org.eclipse.emf.cdo.common.model.CDOModelUtil;
+import org.eclipse.emf.cdo.common.model.CDOPackageUnit;
+import org.eclipse.emf.cdo.common.revision.CDOIDAndBranch;
+import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionKey;
+import org.eclipse.emf.cdo.common.revision.CDORevisionUtil;
+import org.eclipse.emf.cdo.common.revision.delta.CDOAddFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOContainerFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDeltaVisitor;
+import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOSetFeatureDelta;
+import org.eclipse.emf.cdo.common.util.CDOCommonUtil;
+import org.eclipse.emf.cdo.common.util.CDOQueryInfo;
+import org.eclipse.emf.cdo.internal.common.commit.CDOCommitDataImpl;
+import org.eclipse.emf.cdo.internal.common.commit.FailureCommitInfo;
+import org.eclipse.emf.cdo.internal.common.model.CDOPackageRegistryImpl;
+import org.eclipse.emf.cdo.internal.server.bundle.OM;
+import org.eclipse.emf.cdo.server.ContainmentCycleDetectedException;
+import org.eclipse.emf.cdo.server.IStoreAccessor;
+import org.eclipse.emf.cdo.server.IStoreAccessor.QueryXRefsContext;
+import org.eclipse.emf.cdo.server.IView;
+import org.eclipse.emf.cdo.server.StoreThreadLocal;
+import org.eclipse.emf.cdo.spi.common.commit.InternalCDOCommitInfoManager;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageInfo;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit;
+import org.eclipse.emf.cdo.spi.common.revision.CDOFeatureDeltaVisitorImpl;
+import org.eclipse.emf.cdo.spi.common.revision.CDOIDMapper;
+import org.eclipse.emf.cdo.spi.common.revision.CDOReferenceAdjuster;
+import org.eclipse.emf.cdo.spi.common.revision.DetachedCDORevision;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionDelta;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager;
+import org.eclipse.emf.cdo.spi.common.revision.StubCDORevision;
+import org.eclipse.emf.cdo.spi.server.InternalCommitContext;
+import org.eclipse.emf.cdo.spi.server.InternalLockManager;
+import org.eclipse.emf.cdo.spi.server.InternalRepository;
+import org.eclipse.emf.cdo.spi.server.InternalSession;
+import org.eclipse.emf.cdo.spi.server.InternalTransaction;
+
+import org.eclipse.net4j.util.CheckUtil;
+import org.eclipse.net4j.util.ObjectUtil;
+import org.eclipse.net4j.util.StringUtil;
+import org.eclipse.net4j.util.collection.IndexedList;
+import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
+import org.eclipse.net4j.util.concurrent.RWOLockManager.LockState;
+import org.eclipse.net4j.util.io.ExtendedDataInputStream;
+import org.eclipse.net4j.util.lifecycle.LifecycleUtil;
+import org.eclipse.net4j.util.om.monitor.Monitor;
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.ConcurrentModificationException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * @author Simon McDuff
+ * @since 2.0
+ */
+public class TransactionCommitContext implements InternalCommitContext
+{
+  private static final InternalCDORevision DETACHED = new StubCDORevision(null);
+
+  private final InternalTransaction transaction;
+
+  private InternalRepository repository;
+
+  private InternalCDORevisionManager revisionManager;
+
+  private InternalLockManager lockManager;
+
+  private InternalCDOPackageRegistry repositoryPackageRegistry;
+
+  private boolean packageRegistryLocked;
+
+  private TransactionPackageRegistry packageRegistry;
+
+  private IStoreAccessor accessor;
+
+  private long timeStamp = CDORevision.UNSPECIFIED_DATE;
+
+  private long previousTimeStamp = CDORevision.UNSPECIFIED_DATE;
+
+  private String commitComment;
+
+  private InternalCDOPackageUnit[] newPackageUnits = new InternalCDOPackageUnit[0];
+
+  private InternalCDORevision[] newObjects = new InternalCDORevision[0];
+
+  private InternalCDORevisionDelta[] dirtyObjectDeltas = new InternalCDORevisionDelta[0];
+
+  private CDOID[] detachedObjects = new CDOID[0];
+
+  private Map<CDOID, EClass> detachedObjectTypes;
+
+  private InternalCDORevision[] dirtyObjects = new InternalCDORevision[0];
+
+  private InternalCDORevision[] cachedDetachedRevisions = new InternalCDORevision[0];
+
+  private Map<CDOID, InternalCDORevision> cachedRevisions;
+
+  private Set<Object> lockedObjects = new HashSet<Object>();
+
+  private List<CDOID> lockedTargets;
+
+  private ConcurrentMap<CDOID, CDOID> idMappings = new ConcurrentHashMap<CDOID, CDOID>();
+
+  private CDOReferenceAdjuster idMapper = new CDOIDMapper(idMappings);
+
+  private String rollbackMessage;
+
+  private List<CDOIDReference> xRefs;
+
+  private List<LockState<Object, IView>> postCommitLockStates;
+
+  private boolean ensuringReferentialIntegrity;
+
+  private boolean autoReleaseLocksEnabled;
+
+  private ExtendedDataInputStream lobs;
+
+  public TransactionCommitContext(InternalTransaction transaction)
+  {
+    this.transaction = transaction;
+
+    repository = transaction.getRepository();
+    revisionManager = repository.getRevisionManager();
+    lockManager = repository.getLockManager();
+    ensuringReferentialIntegrity = repository.isEnsuringReferentialIntegrity();
+
+    repositoryPackageRegistry = repository.getPackageRegistry(false);
+    packageRegistry = new TransactionPackageRegistry(repositoryPackageRegistry);
+    packageRegistry.activate();
+  }
+
+  public InternalTransaction getTransaction()
+  {
+    return transaction;
+  }
+
+  public CDOBranchPoint getBranchPoint()
+  {
+    return transaction.getBranch().getPoint(timeStamp);
+  }
+
+  public String getUserID()
+  {
+    return transaction.getSession().getUserID();
+  }
+
+  public String getCommitComment()
+  {
+    return commitComment;
+  }
+
+  public boolean isAutoReleaseLocksEnabled()
+  {
+    return autoReleaseLocksEnabled;
+  }
+
+  public String getRollbackMessage()
+  {
+    return rollbackMessage;
+  }
+
+  public List<CDOIDReference> getXRefs()
+  {
+    return xRefs;
+  }
+
+  public InternalCDOPackageRegistry getPackageRegistry()
+  {
+    return packageRegistry;
+  }
+
+  public InternalCDOPackageUnit[] getNewPackageUnits()
+  {
+    return newPackageUnits;
+  }
+
+  public InternalCDORevision[] getNewObjects()
+  {
+    return newObjects;
+  }
+
+  public InternalCDORevision[] getDirtyObjects()
+  {
+    return dirtyObjects;
+  }
+
+  public CDOID[] getDetachedObjects()
+  {
+    return detachedObjects;
+  }
+
+  public Map<CDOID, EClass> getDetachedObjectTypes()
+  {
+    return detachedObjectTypes;
+  }
+
+  public InternalCDORevision[] getDetachedRevisions()
+  {
+    // TODO This array can contain null values as they only come from the cache
+    for (InternalCDORevision cachedDetachedRevision : cachedDetachedRevisions)
+    {
+      if (cachedDetachedRevision == null)
+      {
+        throw new AssertionError("Detached revisions are incomplete");
+      }
+    }
+
+    return cachedDetachedRevisions;
+  }
+
+  public InternalCDORevisionDelta[] getDirtyObjectDeltas()
+  {
+    return dirtyObjectDeltas;
+  }
+
+  public CDORevision getRevision(CDOID id)
+  {
+    if (cachedRevisions == null)
+    {
+      cachedRevisions = cacheRevisions();
+    }
+
+    // Try "after state"
+    InternalCDORevision revision = cachedRevisions.get(id);
+    if (revision == DETACHED)
+    {
+      return null;
+    }
+
+    if (revision != null)
+    {
+      return revision;
+    }
+
+    // Fall back to "before state"
+    return transaction.getRevision(id);
+  }
+
+  private Map<CDOID, InternalCDORevision> cacheRevisions()
+  {
+    Map<CDOID, InternalCDORevision> cache = new HashMap<CDOID, InternalCDORevision>();
+    if (newObjects != null)
+    {
+      for (int i = 0; i < newObjects.length; i++)
+      {
+        InternalCDORevision revision = newObjects[i];
+        cache.put(revision.getID(), revision);
+      }
+    }
+
+    if (dirtyObjects != null)
+    {
+      for (int i = 0; i < dirtyObjects.length; i++)
+      {
+        InternalCDORevision revision = dirtyObjects[i];
+        cache.put(revision.getID(), revision);
+      }
+    }
+
+    if (detachedObjects != null)
+    {
+      for (int i = 0; i < detachedObjects.length; i++)
+      {
+        cache.put(detachedObjects[i], DETACHED);
+      }
+    }
+
+    return cache;
+  }
+
+  public Map<CDOID, CDOID> getIDMappings()
+  {
+    return Collections.unmodifiableMap(idMappings);
+  }
+
+  public void addIDMapping(CDOID oldID, CDOID newID)
+  {
+    if (CDOIDUtil.isNull(newID) || newID.isTemporary())
+    {
+      throw new IllegalStateException("newID=" + newID); //$NON-NLS-1$
+    }
+
+    CDOID previousMapping = idMappings.putIfAbsent(oldID, newID);
+    if (previousMapping != null)
+    {
+      throw new IllegalStateException("previousMapping != null"); //$NON-NLS-1$
+    }
+  }
+
+  public void applyIDMappings(OMMonitor monitor)
+  {
+    if (idMappings.isEmpty())
+    {
+      return;
+    }
+
+    try
+    {
+      monitor.begin(newObjects.length + dirtyObjects.length + dirtyObjectDeltas.length);
+      applyIDMappings(newObjects, monitor.fork(newObjects.length));
+      applyIDMappings(dirtyObjects, monitor.fork(dirtyObjects.length));
+      for (CDORevisionDelta dirtyObjectDelta : dirtyObjectDeltas)
+      {
+        ((InternalCDORevisionDelta)dirtyObjectDelta).adjustReferences(idMapper);
+        monitor.worked();
+      }
+    }
+    finally
+    {
+      monitor.done();
+    }
+  }
+
+  public void preWrite()
+  {
+    // Allocate a store writer
+    accessor = repository.getStore().getWriter(transaction);
+
+    // Make the store writer available in a ThreadLocal variable
+    StoreThreadLocal.setAccessor(accessor);
+    StoreThreadLocal.setCommitContext(this);
+  }
+
+  public void setNewPackageUnits(InternalCDOPackageUnit[] newPackageUnits)
+  {
+    this.newPackageUnits = newPackageUnits;
+  }
+
+  public void setNewObjects(InternalCDORevision[] newObjects)
+  {
+    this.newObjects = newObjects;
+  }
+
+  public void setDirtyObjectDeltas(InternalCDORevisionDelta[] dirtyObjectDeltas)
+  {
+    this.dirtyObjectDeltas = dirtyObjectDeltas;
+  }
+
+  public void setDetachedObjects(CDOID[] detachedObjects)
+  {
+    this.detachedObjects = detachedObjects;
+  }
+
+  public void setDetachedObjectTypes(Map<CDOID, EClass> detachedObjectTypes)
+  {
+    this.detachedObjectTypes = detachedObjectTypes;
+  }
+
+  public void setAutoReleaseLocksEnabled(boolean on)
+  {
+    autoReleaseLocksEnabled = on;
+  }
+
+  public void setCommitComment(String commitComment)
+  {
+    this.commitComment = commitComment;
+  }
+
+  public ExtendedDataInputStream getLobs()
+  {
+    return lobs;
+  }
+
+  public void setLobs(ExtendedDataInputStream in)
+  {
+    lobs = in;
+  }
+
+  /**
+   * @since 2.0
+   */
+  public void write(OMMonitor monitor)
+  {
+    try
+    {
+      monitor.begin(107);
+      dirtyObjects = new InternalCDORevision[dirtyObjectDeltas.length];
+
+      if (newPackageUnits.length != 0)
+      {
+        repository.getPackageRegistryCommitLock().acquire();
+        packageRegistryLocked = true;
+
+        List<InternalCDOPackageUnit> noDuplicates = new ArrayList<InternalCDOPackageUnit>();
+        for (InternalCDOPackageUnit newPackageUnit : newPackageUnits)
+        {
+          String id = newPackageUnit.getID();
+          if (!repositoryPackageRegistry.containsKey(id))
+          {
+            noDuplicates.add(newPackageUnit);
+          }
+        }
+
+        int newSize = noDuplicates.size();
+        if (newPackageUnits.length != newSize)
+        {
+          newPackageUnits = noDuplicates.toArray(new InternalCDOPackageUnit[newSize]);
+        }
+      }
+
+      lockObjects(); // Can take long and must come before setTimeStamp()
+      monitor.worked();
+
+      setTimeStamp(monitor.fork());
+
+      adjustForCommit();
+      monitor.worked();
+
+      computeDirtyObjects(monitor.fork());
+
+      checkXRefs();
+      monitor.worked();
+
+      if (rollbackMessage == null)
+      {
+        detachObjects(monitor.fork());
+        repository.notifyWriteAccessHandlers(transaction, this, true, monitor.fork());
+        accessor.write(this, monitor.fork(100));
+      }
+    }
+    catch (Throwable t)
+    {
+      handleException(t);
+    }
+    finally
+    {
+      finishMonitor(monitor);
+    }
+  }
+
+  public void commit(OMMonitor monitor)
+  {
+    try
+    {
+      monitor.begin(101);
+      accessor.commit(monitor.fork(100));
+      updateInfraStructure(monitor.fork());
+
+      // Bugzilla 297940
+      repository.endCommit(timeStamp);
+    }
+    catch (Throwable ex)
+    {
+      handleException(ex);
+    }
+    finally
+    {
+      finishMonitor(monitor);
+    }
+  }
+
+  public List<LockState<Object, IView>> getPostCommmitLockStates()
+  {
+    return postCommitLockStates;
+  }
+
+  private void handleException(Throwable ex)
+  {
+    try
+    {
+      OM.LOG.error(ex);
+      String storeClass = repository.getStore().getClass().getSimpleName();
+      rollback("Rollback in " + storeClass + ": " + StringUtil.formatException(ex)); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+    catch (Exception ex1)
+    {
+      if (rollbackMessage == null)
+      {
+        rollbackMessage = ex1.getMessage();
+      }
+
+      try
+      {
+        OM.LOG.error(ex1);
+      }
+      catch (Exception ignore)
+      {
+      }
+    }
+  }
+
+  private void finishMonitor(OMMonitor monitor)
+  {
+    try
+    {
+      monitor.done();
+    }
+    catch (Exception ex)
+    {
+      try
+      {
+        OM.LOG.warn(ex);
+      }
+      catch (Exception ignore)
+      {
+      }
+    }
+  }
+
+  private void setTimeStamp(OMMonitor mmonitor)
+  {
+    long[] times = createTimeStamp(mmonitor); // Could throw an exception
+    timeStamp = times[0];
+    previousTimeStamp = times[1];
+    CheckUtil.checkState(timeStamp != CDOBranchPoint.UNSPECIFIED_DATE, "Commit timestamp must not be 0");
+  }
+
+  protected long[] createTimeStamp(OMMonitor monitor)
+  {
+    return repository.createCommitTimeStamp(monitor);
+  }
+
+  protected long getTimeStamp()
+  {
+    return timeStamp;
+  }
+
+  protected void setTimeStamp(long timeStamp)
+  {
+    repository.forceCommitTimeStamp(timeStamp, new Monitor());
+    this.timeStamp = timeStamp;
+  }
+
+  public long getPreviousTimeStamp()
+  {
+    return previousTimeStamp;
+  }
+
+  public void postCommit(boolean success)
+  {
+    if (packageRegistryLocked)
+    {
+      repository.getPackageRegistryCommitLock().release();
+    }
+
+    try
+    {
+      InternalSession sender = transaction.getSession();
+      CDOCommitInfo commitInfo = success ? createCommitInfo() : createFailureCommitInfo();
+
+      repository.sendCommitNotification(sender, commitInfo);
+    }
+    catch (Exception ex)
+    {
+      OM.LOG.warn("A problem occured while notifying other sessions", ex);
+    }
+    finally
+    {
+      StoreThreadLocal.release();
+      accessor = null;
+      lockedTargets = null;
+
+      if (packageRegistry != null)
+      {
+        packageRegistry.deactivate();
+        packageRegistry = null;
+      }
+    }
+  }
+
+  public CDOCommitInfo createCommitInfo()
+  {
+    CDOBranch branch = transaction.getBranch();
+    String userID = transaction.getSession().getUserID();
+    CDOCommitData commitData = createCommitData();
+
+    InternalCDOCommitInfoManager commitInfoManager = repository.getCommitInfoManager();
+    return commitInfoManager.createCommitInfo(branch, timeStamp, previousTimeStamp, userID, commitComment, commitData);
+  }
+
+  public CDOCommitInfo createFailureCommitInfo()
+  {
+    return new FailureCommitInfo(timeStamp, previousTimeStamp);
+  }
+
+  private CDOCommitData createCommitData()
+  {
+    List<CDOPackageUnit> newPackageUnitsCollection = new IndexedList.ArrayBacked<CDOPackageUnit>()
+    {
+      @Override
+      protected CDOPackageUnit[] getArray()
+      {
+        return newPackageUnits;
+      }
+    };
+
+    List<CDOIDAndVersion> newObjectsCollection = new IndexedList.ArrayBacked<CDOIDAndVersion>()
+    {
+      @Override
+      protected CDOIDAndVersion[] getArray()
+      {
+        return newObjects;
+      }
+    };
+
+    List<CDORevisionKey> changedObjectsCollection = new IndexedList.ArrayBacked<CDORevisionKey>()
+    {
+      @Override
+      protected CDORevisionKey[] getArray()
+      {
+        return dirtyObjectDeltas;
+      }
+    };
+
+    List<CDOIDAndVersion> detachedObjectsCollection = new IndexedList<CDOIDAndVersion>()
+    {
+      @Override
+      public CDOIDAndVersion get(int i)
+      {
+        if (cachedDetachedRevisions[i] != null)
+        {
+          return cachedDetachedRevisions[i];
+        }
+
+        return CDOIDUtil.createIDAndVersion(detachedObjects[i], CDORevision.UNSPECIFIED_VERSION);
+      }
+
+      @Override
+      public int size()
+      {
+        return detachedObjects.length;
+      }
+    };
+
+    return new CDOCommitDataImpl(newPackageUnitsCollection, newObjectsCollection, changedObjectsCollection,
+        detachedObjectsCollection);
+  }
+
+  protected void adjustForCommit()
+  {
+    for (InternalCDOPackageUnit newPackageUnit : newPackageUnits)
+    {
+      newPackageUnit.setTimeStamp(timeStamp);
+    }
+
+    CDOBranch branch = transaction.getBranch();
+    for (InternalCDORevision newObject : newObjects)
+    {
+      newObject.adjustForCommit(branch, timeStamp);
+    }
+  }
+
+  protected void lockObjects() throws InterruptedException
+  {
+    lockedObjects.clear();
+    lockedTargets = null;
+
+    try
+    {
+      final boolean supportingBranches = repository.isSupportingBranches();
+
+      CDOFeatureDeltaVisitor deltaTargetLocker = null;
+      if (ensuringReferentialIntegrity)
+      {
+        final Set<CDOID> newIDs = new HashSet<CDOID>();
+        for (int i = 0; i < newObjects.length; i++)
+        {
+          InternalCDORevision newRevision = newObjects[i];
+          CDOID newID = newRevision.getID();
+          if (newID instanceof CDOIDObject)
+          {
+            // After merges newObjects may contain non-TEMP ids
+            newIDs.add(newID);
+          }
+        }
+
+        deltaTargetLocker = new CDOFeatureDeltaVisitorImpl()
+        {
+          @Override
+          public void visit(CDOAddFeatureDelta delta)
+          {
+            lockTarget(delta.getValue(), newIDs, supportingBranches);
+          }
+
+          @Override
+          public void visit(CDOSetFeatureDelta delta)
+          {
+            lockTarget(delta.getValue(), newIDs, supportingBranches);
+          }
+        };
+
+        CDOReferenceAdjuster revisionTargetLocker = new CDOReferenceAdjuster()
+        {
+          public Object adjustReference(Object value, EStructuralFeature feature, int index)
+          {
+            lockTarget(value, newIDs, supportingBranches);
+            return value;
+          }
+        };
+
+        for (int i = 0; i < newObjects.length; i++)
+        {
+          InternalCDORevision newRevision = newObjects[i];
+          newRevision.adjustReferences(revisionTargetLocker);
+        }
+      }
+
+      for (int i = 0; i < dirtyObjectDeltas.length; i++)
+      {
+        InternalCDORevisionDelta delta = dirtyObjectDeltas[i];
+        CDOID id = delta.getID();
+        Object key = lockManager.getLockKey(id, transaction.getBranch());
+        lockedObjects.add(new DeltaLockWrapper(key, delta));
+
+        if (hasContainmentChanges(delta))
+        {
+          if (isContainerLocked(delta))
+          {
+            throw new ContainmentCycleDetectedException("Parent (" + key
+                + ") is already locked for containment changes");
+          }
+        }
+      }
+
+      for (int i = 0; i < dirtyObjectDeltas.length; i++)
+      {
+        InternalCDORevisionDelta delta = dirtyObjectDeltas[i];
+        if (deltaTargetLocker != null)
+        {
+          delta.accept(deltaTargetLocker);
+        }
+      }
+
+      for (int i = 0; i < detachedObjects.length; i++)
+      {
+        CDOID id = detachedObjects[i];
+        Object key = lockManager.getLockKey(id, transaction.getBranch());
+        lockedObjects.add(key);
+      }
+
+      if (!lockedObjects.isEmpty())
+      {
+        // First lock all objects (incl. possible ref targets).
+        // This is a transient operation, it does not check for existance!
+        lockManager.lock(LockType.WRITE, transaction, lockedObjects, 1000);
+
+        // If all locks could be acquired, check if locked targets do still exist
+        if (lockedTargets != null)
+        {
+          for (CDOID id : lockedTargets)
+          {
+            InternalCDORevision revision = //
+            revisionManager.getRevision(id, transaction, CDORevision.UNCHUNKED, CDORevision.DEPTH_NONE, true);
+
+            if (revision == null || revision instanceof DetachedCDORevision)
+            {
+              throw new IllegalStateException("Object " + id
+                  + " can not be referenced anymore because it has been detached");
+            }
+          }
+        }
+      }
+    }
+    catch (RuntimeException ex)
+    {
+      lockedObjects.clear();
+      lockedTargets = null;
+      throw ex;
+    }
+  }
+
+  /**
+   * Iterates up the eContainers of an object and returns <code>true</code> on the first parent locked by another view.
+   * 
+   * @return <code>true</code> if any parent is locked, <code>false</code> otherwise.
+   */
+  private boolean isContainerLocked(InternalCDORevisionDelta delta)
+  {
+    CDOID id = delta.getID();
+    InternalCDORevision revision = revisionManager.getRevisionByVersion(id, delta, CDORevision.UNCHUNKED, true);
+    if (revision == null)
+    {
+      // Can happen with non-auditing cache
+      throw new ConcurrentModificationException("Attempt by " + transaction + " to modify historical revision: "
+          + CDORevisionUtil.copyRevisionKey(delta));
+    }
+
+    return isContainerLocked(revision);
+  }
+
+  private boolean isContainerLocked(InternalCDORevision revision)
+  {
+    CDOID id = (CDOID)revision.getContainerID();
+    if (CDOIDUtil.isNull(id))
+    {
+      return false;
+    }
+
+    Object key = lockManager.getLockKey(id, transaction.getBranch());
+    DeltaLockWrapper lockWrapper = new DeltaLockWrapper(key, null);
+
+    if (lockManager.hasLockByOthers(LockType.WRITE, transaction, lockWrapper))
+    {
+      Object object = lockManager.getLockEntryObject(lockWrapper);
+      if (object instanceof DeltaLockWrapper)
+      {
+        InternalCDORevisionDelta delta = ((DeltaLockWrapper)object).getDelta();
+        if (delta != null && hasContainmentChanges(delta))
+        {
+          return true;
+        }
+      }
+    }
+
+    InternalCDORevision parent = revisionManager.getRevision(id, transaction, CDORevision.UNCHUNKED,
+        CDORevision.DEPTH_NONE, true);
+
+    if (parent != null)
+    {
+      return isContainerLocked(parent);
+    }
+
+    return false;
+  }
+
+  private boolean hasContainmentChanges(InternalCDORevisionDelta delta)
+  {
+    for (CDOFeatureDelta featureDelta : delta.getFeatureDeltas())
+    {
+      EStructuralFeature feature = featureDelta.getFeature();
+      if (feature instanceof EReference)
+      {
+        if (((EReference)feature).isContainment())
+        {
+          return true;
+        }
+      }
+    }
+
+    return false;
+  }
+
+  private void lockTarget(Object value, Set<CDOID> newIDs, boolean supportingBranches)
+  {
+    if (value instanceof CDOIDObject)
+    {
+      CDOIDObject id = (CDOIDObject)value;
+      if (id.isNull())
+      {
+        return;
+      }
+
+      if (newIDs.contains(id))
+      {
+        // After merges newObjects may contain non-TEMP ids
+        return;
+      }
+
+      if (detachedObjectTypes != null && detachedObjectTypes.containsKey(id))
+      {
+        throw new IllegalStateException("This commit deletes object " + id + " and adds a reference at the same time");
+      }
+
+      // Let this object be locked
+      Object key = lockManager.getLockKey(id, transaction.getBranch());
+      lockedObjects.add(key);
+
+      // Let this object be checked for existance after it has been locked
+      if (lockedTargets == null)
+      {
+        lockedTargets = new ArrayList<CDOID>();
+      }
+
+      lockedTargets.add(id);
+    }
+  }
+
+  protected void checkXRefs()
+  {
+    if (ensuringReferentialIntegrity && detachedObjectTypes != null)
+    {
+      XRefContext context = new XRefContext();
+      xRefs = context.getXRefs(accessor);
+      if (!xRefs.isEmpty())
+      {
+        rollbackMessage = "Referential integrity violated";
+      }
+    }
+  }
+
+  private synchronized void unlockObjects()
+  {
+    if (!lockedObjects.isEmpty())
+    {
+      lockManager.unlock(LockType.WRITE, transaction, lockedObjects);
+      lockedObjects.clear();
+    }
+  }
+
+  private void computeDirtyObjects(OMMonitor monitor)
+  {
+    try
+    {
+      monitor.begin(dirtyObjectDeltas.length);
+      for (int i = 0; i < dirtyObjectDeltas.length; i++)
+      {
+        dirtyObjects[i] = computeDirtyObject(dirtyObjectDeltas[i]);
+        if (dirtyObjects[i] == null)
+        {
+          throw new IllegalStateException("Can not retrieve origin revision for " + dirtyObjectDeltas[i]); //$NON-NLS-1$
+        }
+
+        monitor.worked();
+      }
+    }
+    finally
+    {
+      monitor.done();
+    }
+  }
+
+  private InternalCDORevision computeDirtyObject(InternalCDORevisionDelta delta)
+  {
+    CDOID id = delta.getID();
+
+    InternalCDORevision oldRevision = revisionManager.getRevisionByVersion(id, delta, CDORevision.UNCHUNKED, true);
+    if (oldRevision == null)
+    {
+      throw new IllegalStateException("Origin revision not found for " + delta);
+    }
+
+    CDOBranch branch = transaction.getBranch();
+    if (ObjectUtil.equals(oldRevision.getBranch(), branch) && oldRevision.isHistorical())
+    {
+      throw new ConcurrentModificationException("Attempt by " + transaction + " to modify historical revision: "
+          + oldRevision);
+    }
+
+    // Make sure all chunks are loaded
+    for (EStructuralFeature feature : CDOModelUtil.getAllPersistentFeatures(oldRevision.getEClass()))
+    {
+      if (feature.isMany())
+      {
+        repository.ensureChunk(oldRevision, feature, 0, oldRevision.getList(feature).size());
+      }
+    }
+
+    InternalCDORevision newRevision = oldRevision.copy();
+    newRevision.adjustForCommit(branch, timeStamp);
+
+    delta.apply(newRevision);
+    return newRevision;
+  }
+
+  private void applyIDMappings(InternalCDORevision[] revisions, OMMonitor monitor)
+  {
+    try
+    {
+      monitor.begin(revisions.length);
+      for (InternalCDORevision revision : revisions)
+      {
+        if (revision != null)
+        {
+          CDOID newID = idMappings.get(revision.getID());
+          if (newID != null)
+          {
+            revision.setID(newID);
+          }
+
+          revision.adjustReferences(idMapper);
+          monitor.worked();
+        }
+      }
+    }
+    finally
+    {
+      monitor.done();
+    }
+  }
+
+  public synchronized void rollback(String message)
+  {
+    // Check if we already rolled back
+    if (rollbackMessage == null)
+    {
+      rollbackMessage = message;
+      unlockObjects();
+      if (accessor != null)
+      {
+        try
+        {
+          accessor.rollback();
+        }
+        catch (RuntimeException ex)
+        {
+          OM.LOG.warn("Problem while rolling back  the transaction", ex); //$NON-NLS-1$
+        }
+        finally
+        {
+          repository.failCommit(timeStamp);
+        }
+      }
+    }
+  }
+
+  protected IStoreAccessor getAccessor()
+  {
+    return accessor;
+  }
+
+  private void updateInfraStructure(OMMonitor monitor)
+  {
+    try
+    {
+      monitor.begin(7);
+      addNewPackageUnits(monitor.fork());
+      addRevisions(newObjects, monitor.fork());
+      addRevisions(dirtyObjects, monitor.fork());
+      reviseDetachedObjects(monitor.fork());
+
+      unlockObjects();
+      monitor.worked();
+
+      if (isAutoReleaseLocksEnabled())
+      {
+        postCommitLockStates = repository.getLockManager().unlock2(true, transaction);
+        if (!postCommitLockStates.isEmpty())
+        {
+          sendLockNotifications(postCommitLockStates);
+        }
+      }
+
+      monitor.worked();
+      repository.notifyWriteAccessHandlers(transaction, this, false, monitor.fork());
+    }
+    finally
+    {
+      monitor.done();
+    }
+  }
+
+  private void sendLockNotifications(List<LockState<Object, IView>> newLockStates)
+  {
+    CDOLockState[] newStates = Repository.toCDOLockStates(newLockStates);
+
+    long timeStamp = getTimeStamp();
+    InternalTransaction tx = getTransaction();
+    CDOBranch branch = tx.getBranch();
+    Operation unlock = Operation.UNLOCK;
+
+    CDOLockChangeInfo info = CDOLockUtil.createLockChangeInfo(timeStamp, tx, branch, unlock, null, newStates);
+    repository.getSessionManager().sendLockNotification(tx.getSession(), info);
+  }
+
+  private void addNewPackageUnits(OMMonitor monitor)
+  {
+    InternalCDOPackageRegistry repositoryPackageRegistry = repository.getPackageRegistry(false);
+    synchronized (repositoryPackageRegistry)
+    {
+      try
+      {
+        monitor.begin(newPackageUnits.length);
+        for (int i = 0; i < newPackageUnits.length; i++)
+        {
+          newPackageUnits[i].setState(CDOPackageUnit.State.LOADED);
+          repositoryPackageRegistry.putPackageUnit(newPackageUnits[i]);
+          monitor.worked();
+        }
+      }
+      finally
+      {
+        monitor.done();
+      }
+    }
+  }
+
+  private void addRevisions(CDORevision[] revisions, OMMonitor monitor)
+  {
+    try
+    {
+      monitor.begin(revisions.length);
+      for (CDORevision revision : revisions)
+      {
+        if (revision != null)
+        {
+          revisionManager.addRevision(revision);
+        }
+
+        monitor.worked();
+      }
+    }
+    finally
+    {
+      monitor.done();
+    }
+  }
+
+  private void reviseDetachedObjects(OMMonitor monitor)
+  {
+    try
+    {
+      monitor.begin(cachedDetachedRevisions.length);
+      long revised = getBranchPoint().getTimeStamp() - 1;
+      for (InternalCDORevision revision : cachedDetachedRevisions)
+      {
+        if (revision != null)
+        {
+          revision.setRevised(revised);
+        }
+
+        monitor.worked();
+      }
+    }
+    finally
+    {
+      monitor.done();
+    }
+  }
+
+  private void detachObjects(OMMonitor monitor)
+  {
+    int size = detachedObjects.length;
+    cachedDetachedRevisions = new InternalCDORevision[size];
+
+    CDOID[] detachedObjects = getDetachedObjects();
+
+    try
+    {
+      monitor.begin(size);
+      for (int i = 0; i < size; i++)
+      {
+        CDOID id = detachedObjects[i];
+
+        // Remember the cached revision that must be revised after successful commit through updateInfraStructure
+        cachedDetachedRevisions[i] = (InternalCDORevision)revisionManager.getCache().getRevision(id, transaction);
+        monitor.worked();
+      }
+    }
+    finally
+    {
+      monitor.done();
+    }
+  }
+
+  @Override
+  public String toString()
+  {
+    return MessageFormat.format("TransactionCommitContext[{0}, {1}, {2}]", transaction.getSession(), transaction, //$NON-NLS-1$
+        CDOCommonUtil.formatTimeStamp(timeStamp));
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  public static final class TransactionPackageRegistry extends CDOPackageRegistryImpl
+  {
+    private static final long serialVersionUID = 1L;
+
+    public TransactionPackageRegistry(InternalCDOPackageRegistry repositoryPackageRegistry)
+    {
+      delegateRegistry = repositoryPackageRegistry;
+      setPackageLoader(repositoryPackageRegistry.getPackageLoader());
+    }
+
+    @Override
+    public synchronized void putPackageUnit(InternalCDOPackageUnit packageUnit)
+    {
+      LifecycleUtil.checkActive(this);
+      packageUnit.setPackageRegistry(this);
+      for (InternalCDOPackageInfo packageInfo : packageUnit.getPackageInfos())
+      {
+        EPackage ePackage = packageInfo.getEPackage();
+        basicPut(ePackage.getNsURI(), ePackage);
+      }
+
+      resetInternalCaches();
+    }
+
+    @Override
+    protected void disposePackageUnits()
+    {
+      // Do nothing
+    }
+
+    @Override
+    public Collection<Object> values()
+    {
+      throw new UnsupportedOperationException();
+    }
+  }
+
+  /**
+   * @author Martin Fluegge
+   */
+  private static final class DeltaLockWrapper implements CDOIDAndBranch
+  {
+    private Object key;
+
+    private InternalCDORevisionDelta delta;
+
+    public DeltaLockWrapper(Object key, InternalCDORevisionDelta delta)
+    {
+      this.key = key;
+      this.delta = delta;
+    }
+
+    public Object getKey()
+    {
+      return key;
+    }
+
+    public InternalCDORevisionDelta getDelta()
+    {
+      return delta;
+    }
+
+    public CDOID getID()
+    {
+      return key instanceof CDOIDAndBranch ? ((CDOIDAndBranch)key).getID() : (CDOID)key;
+    }
+
+    public CDOBranch getBranch()
+    {
+      return key instanceof CDOIDAndBranch ? ((CDOIDAndBranch)key).getBranch() : null;
+    }
+
+    @Override
+    public boolean equals(Object obj)
+    {
+      if (obj instanceof DeltaLockWrapper)
+      {
+        DeltaLockWrapper wrapper = (DeltaLockWrapper)obj;
+        return key.equals(wrapper.getKey());
+      }
+
+      return key.equals(obj);
+    }
+
+    @Override
+    public int hashCode()
+    {
+      return key.hashCode();
+    }
+
+    @Override
+    public String toString()
+    {
+      return key.toString();
+    }
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  private final class XRefContext implements QueryXRefsContext
+  {
+    private Map<EClass, List<EReference>> sourceCandidates = new HashMap<EClass, List<EReference>>();
+
+    private Set<CDOID> detachedIDs = new HashSet<CDOID>();
+
+    private Set<CDOID> dirtyIDs = new HashSet<CDOID>();
+
+    private List<CDOIDReference> result = new ArrayList<CDOIDReference>();
+
+    public XRefContext()
+    {
+      XRefsQueryHandler.collectSourceCandidates(transaction, detachedObjectTypes.values(), sourceCandidates);
+
+      for (CDOID id : detachedObjects)
+      {
+        detachedIDs.add(id);
+      }
+
+      for (InternalCDORevision revision : dirtyObjects)
+      {
+        dirtyIDs.add(revision.getID());
+      }
+    }
+
+    public List<CDOIDReference> getXRefs(IStoreAccessor accessor)
+    {
+      accessor.queryXRefs(this);
+      checkDirtyObjects();
+      return result;
+    }
+
+    private void checkDirtyObjects()
+    {
+      final CDOID[] dirtyID = { null };
+      CDOReferenceAdjuster dirtyObjectChecker = new CDOReferenceAdjuster()
+      {
+        public Object adjustReference(Object targetID, EStructuralFeature feature, int index)
+        {
+          if (feature != CDOContainerFeatureDelta.CONTAINER_FEATURE)
+          {
+            if (detachedIDs.contains(targetID))
+            {
+              result.add(new CDOIDReference((CDOID)targetID, dirtyID[0], feature, index));
+            }
+
+          }
+
+          return targetID;
+        }
+      };
+
+      for (InternalCDORevision dirtyObject : dirtyObjects)
+      {
+        dirtyID[0] = dirtyObject.getID();
+        dirtyObject.adjustReferences(dirtyObjectChecker);
+      }
+    }
+
+    public long getTimeStamp()
+    {
+      return CDOBranchPoint.UNSPECIFIED_DATE;
+    }
+
+    public CDOBranch getBranch()
+    {
+      return transaction.getBranch();
+    }
+
+    public Map<CDOID, EClass> getTargetObjects()
+    {
+      return detachedObjectTypes;
+    }
+
+    public EReference[] getSourceReferences()
+    {
+      return new EReference[0];
+    }
+
+    public Map<EClass, List<EReference>> getSourceCandidates()
+    {
+      return sourceCandidates;
+    }
+
+    public int getMaxResults()
+    {
+      return CDOQueryInfo.UNLIMITED_RESULTS;
+    }
+
+    public boolean addXRef(CDOID targetID, CDOID sourceID, EReference sourceReference, int sourceIndex)
+    {
+      if (CDOIDUtil.isNull(targetID))
+      {
+        // Compensate potential issues with the XRef implementation in the store accessor.
+        return true;
+      }
+
+      if (detachedIDs.contains(sourceID))
+      {
+        // Ignore XRefs from objects that are about to be detached themselves by this commit.
+        return true;
+      }
+
+      if (dirtyIDs.contains(sourceID))
+      {
+        // Ignore XRefs from objects that are about to be modified by this commit. They're handled later in getXRefs().
+        return true;
+      }
+
+      result.add(new CDOIDReference(targetID, sourceID, sourceReference, sourceIndex));
+      return true;
+    }
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/View.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/View.java
new file mode 100644
index 0000000..8e72f32
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/View.java
@@ -0,0 +1,287 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Simon McDuff - bug 233490
+ */
+package org.eclipse.emf.cdo.internal.server;
+
+import org.eclipse.emf.cdo.common.CDOCommonView;
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionManager;
+import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+import org.eclipse.emf.cdo.spi.server.InternalRepository;
+import org.eclipse.emf.cdo.spi.server.InternalSession;
+import org.eclipse.emf.cdo.spi.server.InternalView;
+
+import org.eclipse.net4j.util.ObjectUtil;
+import org.eclipse.net4j.util.lifecycle.Lifecycle;
+import org.eclipse.net4j.util.options.IOptionsContainer;
+
+import java.text.MessageFormat;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Eike Stepper
+ */
+public class View extends Lifecycle implements InternalView, CDOCommonView.Options
+{
+  private InternalSession session;
+
+  private final int viewID;
+
+  private final int sessionID; // Needed here so we can compute the hashCode even after session becomes null due to
+                               // deactivation!
+
+  private CDOBranchPoint branchPoint;
+
+  private String durableLockingID;
+
+  private InternalRepository repository;
+
+  private Set<CDOID> changeSubscriptionIDs = new HashSet<CDOID>();
+
+  private boolean lockNotificationsEnabled;
+
+  /**
+   * @since 2.0
+   */
+  public View(InternalSession session, int viewID, CDOBranchPoint branchPoint)
+  {
+    this.session = session;
+    this.viewID = viewID;
+    sessionID = session.getSessionID();
+
+    repository = session.getManager().getRepository();
+    setBranchPoint(branchPoint);
+  }
+
+  public InternalSession getSession()
+  {
+    return session;
+  }
+
+  public int getViewID()
+  {
+    return viewID;
+  }
+
+  public CDOBranch getBranch()
+  {
+    return branchPoint.getBranch();
+  }
+
+  public long getTimeStamp()
+  {
+    return branchPoint.getTimeStamp();
+  }
+
+  public boolean isReadOnly()
+  {
+    return true;
+  }
+
+  public String getDurableLockingID()
+  {
+    return durableLockingID;
+  }
+
+  /**
+   * @since 2.0
+   */
+  public InternalRepository getRepository()
+  {
+    checkOpen();
+    return repository;
+  }
+
+  public InternalCDORevision getRevision(CDOID id)
+  {
+    CDORevisionManager revisionManager = repository.getRevisionManager();
+    return (InternalCDORevision)revisionManager.getRevision(id, this, CDORevision.UNCHUNKED, CDORevision.DEPTH_NONE,
+        true);
+  }
+
+  public void changeTarget(CDOBranchPoint branchPoint, List<CDOID> invalidObjects,
+      List<CDORevisionDelta> allChangedObjects, List<CDOID> allDetachedObjects)
+  {
+    List<CDORevision> oldRevisions = getRevisions(invalidObjects);
+    setBranchPoint(branchPoint);
+    List<CDORevision> newRevisions = getRevisions(invalidObjects);
+
+    Iterator<CDORevision> it = newRevisions.iterator();
+    for (CDORevision oldRevision : oldRevisions)
+    {
+      CDORevision newRevision = it.next();
+      if (newRevision == null)
+      {
+        allDetachedObjects.add(oldRevision.getID());
+      }
+      else if (newRevision != oldRevision)
+      {
+        CDORevisionDelta delta = newRevision.compare(oldRevision);
+        allChangedObjects.add(delta);
+      }
+    }
+  }
+
+  private List<CDORevision> getRevisions(List<CDOID> ids)
+  {
+    return repository.getRevisionManager().getRevisions(ids, branchPoint, CDORevision.UNCHUNKED,
+        CDORevision.DEPTH_NONE, true);
+  }
+
+  public void setBranchPoint(CDOBranchPoint branchPoint)
+  {
+    checkOpen();
+    long timeStamp = branchPoint.getTimeStamp();
+    branchPoint = branchPoint.getBranch().getPoint(timeStamp);
+    validateTimeStamp(timeStamp);
+    this.branchPoint = branchPoint;
+  }
+
+  protected void validateTimeStamp(long timeStamp) throws IllegalArgumentException
+  {
+    if (timeStamp != UNSPECIFIED_DATE)
+    {
+      repository.validateTimeStamp(timeStamp);
+    }
+  }
+
+  public void setDurableLockingID(String durableLockingID)
+  {
+    this.durableLockingID = durableLockingID;
+  }
+
+  /**
+   * @since 2.0
+   */
+  public synchronized void subscribe(CDOID id)
+  {
+    checkOpen();
+    changeSubscriptionIDs.add(id);
+  }
+
+  /**
+   * @since 2.0
+   */
+  public synchronized void unsubscribe(CDOID id)
+  {
+    checkOpen();
+    changeSubscriptionIDs.remove(id);
+  }
+
+  /**
+   * @since 2.0
+   */
+  public synchronized boolean hasSubscription(CDOID id)
+  {
+    checkOpen();
+    return changeSubscriptionIDs.contains(id);
+  }
+
+  /**
+   * @since 2.0
+   */
+  public synchronized void clearChangeSubscription()
+  {
+    checkOpen();
+    changeSubscriptionIDs.clear();
+  }
+
+  @Override
+  public int hashCode()
+  {
+    return ObjectUtil.hashCode(sessionID, viewID);
+  }
+
+  @Override
+  public String toString()
+  {
+    int sessionID = session == null ? 0 : session.getSessionID();
+    return MessageFormat.format("{0}[{1}:{2}]", getClassName(), sessionID, viewID); //$NON-NLS-1$
+  }
+
+  protected String getClassName()
+  {
+    return "View"; //$NON-NLS-1$
+  }
+
+  /**
+   * @since 2.0
+   */
+  public void close()
+  {
+    deactivate();
+  }
+
+  @Override
+  protected void doDeactivate() throws Exception
+  {
+    if (!isClosed())
+    {
+      session.viewClosed(this);
+    }
+
+    super.doDeactivate();
+  }
+
+  /**
+   * @since 2.0
+   */
+  public void doClose()
+  {
+    clearChangeSubscription();
+    changeSubscriptionIDs = null;
+    session = null;
+    repository = null;
+  }
+
+  /**
+   * @since 2.0
+   */
+  public boolean isClosed()
+  {
+    return repository == null;
+  }
+
+  private void checkOpen()
+  {
+    if (isClosed())
+    {
+      throw new IllegalStateException("View closed"); //$NON-NLS-1$
+    }
+  }
+
+  public IOptionsContainer getContainer()
+  {
+    return this;
+  }
+
+  public Options options()
+  {
+    return this;
+  }
+
+  public boolean isLockNotificationEnabled()
+  {
+    return lockNotificationsEnabled;
+  }
+
+  public void setLockNotificationEnabled(boolean enable)
+  {
+    lockNotificationsEnabled = enable;
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/XATransactionCommitContext.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/XATransactionCommitContext.java
new file mode 100644
index 0000000..a3c23c0
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/XATransactionCommitContext.java
@@ -0,0 +1,185 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Simon McDuff - initial API and implementation
+ *    Eike Stepper - maintenance
+ */
+package org.eclipse.emf.cdo.internal.server;
+
+import org.eclipse.emf.cdo.internal.server.bundle.OM;
+import org.eclipse.emf.cdo.server.StoreThreadLocal;
+import org.eclipse.emf.cdo.spi.server.InternalRepository;
+import org.eclipse.emf.cdo.spi.server.InternalTransaction;
+
+import org.eclipse.net4j.util.WrappedException;
+import org.eclipse.net4j.util.concurrent.ConcurrentValue;
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+import org.eclipse.net4j.util.om.trace.ContextTracer;
+
+/**
+ * @author Simon McDuff
+ * @since 2.0
+ */
+public class XATransactionCommitContext extends TransactionCommitContext
+{
+  private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_TRANSACTION, XATransactionCommitContext.class);
+
+  private ConcurrentValue<CommitState> state = new ConcurrentValue<CommitState>(CommitState.STARTING);
+
+  public XATransactionCommitContext(InternalTransaction transaction)
+  {
+    super(transaction);
+  }
+
+  public ConcurrentValue<CommitState> getState()
+  {
+    return state;
+  }
+
+  @Override
+  public void preWrite()
+  {
+    super.preWrite();
+    StoreThreadLocal.setAccessor(null);
+  }
+
+  @Override
+  public void commit(OMMonitor monitor)
+  {
+    StoreThreadLocal.setAccessor(getAccessor());
+    try
+    {
+      super.commit(monitor);
+    }
+    finally
+    {
+      StoreThreadLocal.setAccessor(null);
+    }
+  }
+
+  @Override
+  public void write(OMMonitor monitor)
+  {
+    StoreThreadLocal.setAccessor(getAccessor());
+    try
+    {
+      super.write(monitor);
+    }
+    finally
+    {
+      StoreThreadLocal.setAccessor(null);
+    }
+  }
+
+  @Override
+  public void postCommit(boolean success)
+  {
+    StoreThreadLocal.setAccessor(getAccessor());
+    InternalRepository repository = getTransaction().getRepository();
+    repository.getCommitManager().remove(this);
+    super.postCommit(success);
+  }
+
+  @Override
+  public synchronized void rollback(String message)
+  {
+    super.rollback(message);
+
+    // Change the state to unblock call.
+    state.set(CommitState.ROLLED_BACK);
+  }
+
+  /**
+   * Wait until another thread fills ID mapping for external objects.
+   */
+  @Override
+  public void applyIDMappings(OMMonitor monitor)
+  {
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Notify phase2 to fill ID mapping."); //$NON-NLS-1$
+    }
+
+    state.set(CommitState.APPLY_ID_MAPPING);
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Waiting for phase2 to be completed before continueing."); //$NON-NLS-1$
+    }
+
+    try
+    {
+      state.acquire(PHASEAPPLYMAPPING_DONE);
+    }
+    catch (InterruptedException ex)
+    {
+      throw WrappedException.wrap(ex);
+    }
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Received signal to continue."); //$NON-NLS-1$
+    }
+
+    super.applyIDMappings(monitor);
+  }
+
+  /**
+   * Object to test if the process is at ApplyIDMapping
+   */
+  final public static Object PHASEAPPLYMAPPING = new Object()
+  {
+    @Override
+    public int hashCode()
+    {
+      return CommitState.APPLY_ID_MAPPING.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object object)
+    {
+      if (object == CommitState.ROLLED_BACK)
+      {
+        throw new RuntimeException("RolledBack"); //$NON-NLS-1$
+      }
+
+      return CommitState.APPLY_ID_MAPPING == object;
+    }
+  };
+
+  /**
+   * Object to test if the process did applyIDMapping
+   */
+  final public static Object PHASEAPPLYMAPPING_DONE = new Object()
+  {
+    @Override
+    public int hashCode()
+    {
+      return CommitState.APPLY_ID_MAPPING_DONE.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object object)
+    {
+      if (object == CommitState.ROLLED_BACK)
+      {
+        throw new RuntimeException("RolledBack"); //$NON-NLS-1$
+      }
+
+      return CommitState.APPLY_ID_MAPPING_DONE == object;
+    }
+  };
+
+  /**
+   * @author Simon McDuff
+   * @since 2.0
+   */
+  public enum CommitState
+  {
+    STARTING, APPLY_ID_MAPPING, APPLY_ID_MAPPING_DONE, ROLLED_BACK
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/XRefsQueryHandler.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/XRefsQueryHandler.java
new file mode 100644
index 0000000..248d30c
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/XRefsQueryHandler.java
@@ -0,0 +1,357 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Stefan Winkler - Bug 331619 - Support cross-referencing (XRef) for abstract classes and class hierarchies
+ */
+package org.eclipse.emf.cdo.internal.server;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.id.CDOIDReference;
+import org.eclipse.emf.cdo.common.id.CDOIDUtil;
+import org.eclipse.emf.cdo.common.model.CDOClassifierRef;
+import org.eclipse.emf.cdo.common.model.CDOPackageInfo;
+import org.eclipse.emf.cdo.common.model.CDOPackageRegistry;
+import org.eclipse.emf.cdo.common.model.CDOPackageUnit;
+import org.eclipse.emf.cdo.common.model.CDOPackageUnit.State;
+import org.eclipse.emf.cdo.common.model.EMFUtil;
+import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants;
+import org.eclipse.emf.cdo.common.util.CDOQueryInfo;
+import org.eclipse.emf.cdo.server.IQueryContext;
+import org.eclipse.emf.cdo.server.IQueryHandler;
+import org.eclipse.emf.cdo.server.IRepository;
+import org.eclipse.emf.cdo.server.IStore;
+import org.eclipse.emf.cdo.server.IStoreAccessor;
+import org.eclipse.emf.cdo.server.IView;
+import org.eclipse.emf.cdo.server.StoreThreadLocal;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry;
+import org.eclipse.emf.cdo.spi.server.InternalRepository;
+import org.eclipse.emf.cdo.spi.server.QueryHandlerFactory;
+
+import org.eclipse.net4j.util.factory.ProductCreationException;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EClassifier;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+/**
+ * @author Eike Stepper
+ */
+public class XRefsQueryHandler implements IQueryHandler
+{
+  public XRefsQueryHandler()
+  {
+  }
+
+  public void executeQuery(CDOQueryInfo info, IQueryContext context)
+  {
+    IStoreAccessor accessor = StoreThreadLocal.getAccessor();
+    QueryContext xrefsContext = new QueryContext(info, context);
+    accessor.queryXRefs(xrefsContext);
+
+    CDOBranchPoint branchPoint = context;
+    CDOBranch branch = branchPoint.getBranch();
+    while (!branch.isMainBranch() && context.getResultCount() < info.getMaxResults())
+    {
+      branchPoint = branch.getBase();
+      branch = branchPoint.getBranch();
+
+      xrefsContext.setBranchPoint(branchPoint);
+      accessor.queryXRefs(xrefsContext);
+    }
+  }
+
+  public static void collectSourceCandidates(IView view, Collection<EClass> concreteTypes,
+      Map<EClass, List<EReference>> sourceCandidates)
+  {
+    InternalRepository repository = (InternalRepository)view.getRepository();
+    CDOPackageRegistry packageRegistry = repository.getPackageRegistry(false);
+
+    for (CDOPackageInfo packageInfo : packageRegistry.getPackageInfos())
+    {
+      // System.out.println();
+      // System.out.println();
+      // System.out.println(packageInfo);
+      collectSourceCandidates(packageInfo, concreteTypes, sourceCandidates);
+      // for (Entry<EClass, List<EReference>> entry : sourceCandidates.entrySet())
+      // {
+      // System.out.println(" ---> " + entry.getKey().getName());
+      // for (EReference eReference : entry.getValue())
+      // {
+      // System.out.println("      ---> " + eReference.getName());
+      // }
+      // }
+      //
+      // System.out.println();
+      // System.out.println();
+    }
+  }
+
+  public static void collectSourceCandidates(CDOPackageInfo packageInfo, Collection<EClass> concreteTypes,
+      Map<EClass, List<EReference>> sourceCandidates)
+  {
+    State state = packageInfo.getPackageUnit().getState();
+    if (state == CDOPackageUnit.State.LOADED || state == CDOPackageUnit.State.PROXY)
+    {
+      EPackage ePackage = packageInfo.getEPackage();
+      for (EClassifier eClassifier : ePackage.getEClassifiers())
+      {
+        if (eClassifier instanceof EClass)
+        {
+          collectSourceCandidates((EClass)eClassifier, concreteTypes, sourceCandidates);
+        }
+      }
+    }
+  }
+
+  public static void collectSourceCandidates(EClass eClass, Collection<EClass> concreteTypes,
+      Map<EClass, List<EReference>> sourceCandidates)
+  {
+    if (!eClass.isAbstract() && !eClass.isInterface())
+    {
+      for (EStructuralFeature eStructuralFeature : eClass.getEAllStructuralFeatures())
+      {
+        if (eStructuralFeature instanceof EReference && EMFUtil.isPersistent(eStructuralFeature))
+        {
+          collectSourceCandidates(eClass, (EReference)eStructuralFeature, concreteTypes, sourceCandidates);
+        }
+      }
+    }
+  }
+
+  public static void collectSourceCandidates(EReference eReference, Collection<EClass> concreteTypes,
+      Map<EClass, List<EReference>> sourceCandidates, CDOPackageRegistry packageRegistry)
+  {
+    EClass rootClass = eReference.getEContainingClass();
+    collectSourceCandidates(rootClass, eReference, concreteTypes, sourceCandidates);
+
+    Collection<EClass> descendentClasses = packageRegistry.getSubTypes().get(rootClass);
+    if (descendentClasses != null)
+    {
+      for (EClass candidateClass : descendentClasses)
+      {
+        collectSourceCandidates(candidateClass, eReference, concreteTypes, sourceCandidates);
+      }
+    }
+  }
+
+  public static void collectSourceCandidates(EClass eClass, EReference eReference, Collection<EClass> concreteTypes,
+      Map<EClass, List<EReference>> sourceCandidates)
+  {
+    if (!eClass.isAbstract() && !eClass.isInterface())
+    {
+      if (!eReference.isContainer() && !eReference.isContainment())
+      {
+        if (canReference(eReference.getEReferenceType(), concreteTypes))
+        {
+          List<EReference> list = sourceCandidates.get(eClass);
+          if (list == null)
+          {
+            list = new ArrayList<EReference>();
+            sourceCandidates.put(eClass, list);
+          }
+
+          list.add(eReference);
+        }
+      }
+    }
+  }
+
+  private static boolean canReference(EClass declaredType, Collection<EClass> concreteTypes)
+  {
+    for (EClass concreteType : concreteTypes)
+    {
+      if (declaredType.isSuperTypeOf(concreteType))
+      {
+        return true;
+      }
+    }
+
+    return false;
+  }
+
+  /**
+   * @author Eike Stepper
+   * @since 3.0
+   */
+  private static final class QueryContext implements IStoreAccessor.QueryXRefsContext
+  {
+    private CDOQueryInfo info;
+
+    private IQueryContext context;
+
+    private CDOBranchPoint branchPoint;
+
+    private Map<CDOID, EClass> targetObjects;
+
+    private Map<EClass, List<EReference>> sourceCandidates;
+
+    private EReference[] sourceReferences;
+
+    public QueryContext(CDOQueryInfo info, IQueryContext context)
+    {
+      this.info = info;
+      this.context = context;
+      branchPoint = context;
+    }
+
+    public void setBranchPoint(CDOBranchPoint branchPoint)
+    {
+      this.branchPoint = branchPoint;
+    }
+
+    public CDOBranch getBranch()
+    {
+      return branchPoint.getBranch();
+    }
+
+    public long getTimeStamp()
+    {
+      return branchPoint.getTimeStamp();
+    }
+
+    public Map<CDOID, EClass> getTargetObjects()
+    {
+      if (targetObjects == null)
+      {
+        IRepository repository = context.getView().getRepository();
+        IStore store = repository.getStore();
+        CDOPackageRegistry packageRegistry = repository.getPackageRegistry();
+
+        targetObjects = new HashMap<CDOID, EClass>();
+        StringTokenizer tokenizer = new StringTokenizer(info.getQueryString(), "|");
+        while (tokenizer.hasMoreTokens())
+        {
+          String val = tokenizer.nextToken();
+          CDOID id = store.createObjectID(val);
+
+          CDOClassifierRef classifierRef;
+          if (id instanceof CDOClassifierRef.Provider)
+          {
+            classifierRef = ((CDOClassifierRef.Provider)id).getClassifierRef();
+          }
+          else
+          {
+            val = tokenizer.nextToken();
+            classifierRef = new CDOClassifierRef(val);
+          }
+
+          EClass eClass = (EClass)classifierRef.resolve(packageRegistry);
+          targetObjects.put(id, eClass);
+        }
+      }
+
+      return targetObjects;
+    }
+
+    public EReference[] getSourceReferences()
+    {
+      if (sourceReferences == null)
+      {
+        sourceReferences = parseSourceReferences();
+      }
+
+      return sourceReferences;
+    }
+
+    private EReference[] parseSourceReferences()
+    {
+      List<EReference> result = new ArrayList<EReference>();
+      CDOPackageRegistry packageRegistry = context.getView().getRepository().getPackageRegistry();
+
+      String params = (String)info.getParameters().get(CDOProtocolConstants.QUERY_LANGUAGE_XREFS_SOURCE_REFERENCES);
+      if (params == null)
+      {
+        return new EReference[0];
+      }
+
+      StringTokenizer tokenizer = new StringTokenizer(params, "|");
+      while (tokenizer.hasMoreTokens())
+      {
+        String className = tokenizer.nextToken();
+        CDOClassifierRef classifierRef = new CDOClassifierRef(className);
+        EClass eClass = (EClass)classifierRef.resolve(packageRegistry);
+
+        String featureName = tokenizer.nextToken();
+        EReference sourceReference = (EReference)eClass.getEStructuralFeature(featureName);
+        result.add(sourceReference);
+      }
+
+      return result.toArray(new EReference[result.size()]);
+    }
+
+    public Map<EClass, List<EReference>> getSourceCandidates()
+    {
+      if (sourceCandidates == null)
+      {
+        sourceCandidates = new HashMap<EClass, List<EReference>>();
+        Collection<EClass> concreteTypes = getTargetObjects().values();
+        EReference[] sourceReferences = getSourceReferences();
+
+        if (sourceReferences.length != 0)
+        {
+          InternalRepository repository = (InternalRepository)context.getView().getRepository();
+          InternalCDOPackageRegistry packageRegistry = repository.getPackageRegistry(false);
+          for (EReference eReference : sourceReferences)
+          {
+            collectSourceCandidates(eReference, concreteTypes, sourceCandidates, packageRegistry);
+          }
+        }
+        else
+        {
+          collectSourceCandidates(context.getView(), concreteTypes, sourceCandidates);
+        }
+      }
+
+      return sourceCandidates;
+    }
+
+    public int getMaxResults()
+    {
+      return info.getMaxResults();
+    }
+
+    public boolean addXRef(CDOID targetID, CDOID sourceID, EReference sourceReference, int sourceIndex)
+    {
+      if (CDOIDUtil.isNull(targetID))
+      {
+        return true;
+      }
+
+      return context.addResult(new CDOIDReference(targetID, sourceID, sourceReference, sourceIndex));
+    }
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  public static class Factory extends QueryHandlerFactory
+  {
+    public Factory()
+    {
+      super(CDOProtocolConstants.QUERY_LANGUAGE_RESOURCES);
+    }
+
+    @Override
+    public XRefsQueryHandler create(String description) throws ProductCreationException
+    {
+      return new XRefsQueryHandler();
+    }
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/bundle/CDOCommandProvider.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/bundle/CDOCommandProvider.java
new file mode 100644
index 0000000..6f7df7d
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/bundle/CDOCommandProvider.java
@@ -0,0 +1,405 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.internal.server.bundle;
+
+import org.eclipse.emf.cdo.common.lock.IDurableLockingManager;
+import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockArea;
+import org.eclipse.emf.cdo.common.util.CDOCommonUtil;
+import org.eclipse.emf.cdo.server.CDOServerExporter;
+import org.eclipse.emf.cdo.server.CDOServerImporter;
+import org.eclipse.emf.cdo.server.CDOServerUtil;
+import org.eclipse.emf.cdo.server.IRepository;
+import org.eclipse.emf.cdo.server.IStoreAccessor;
+import org.eclipse.emf.cdo.server.StoreThreadLocal;
+import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranch;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageInfo;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit;
+import org.eclipse.emf.cdo.spi.server.InternalRepository;
+import org.eclipse.emf.cdo.spi.server.InternalSession;
+import org.eclipse.emf.cdo.spi.server.InternalSessionManager;
+import org.eclipse.emf.cdo.spi.server.InternalView;
+import org.eclipse.emf.cdo.spi.server.RepositoryConfigurator;
+import org.eclipse.emf.cdo.spi.server.RepositoryFactory;
+
+import org.eclipse.net4j.util.container.IManagedContainer;
+import org.eclipse.net4j.util.io.IOUtil;
+import org.eclipse.net4j.util.lifecycle.LifecycleUtil;
+
+import org.eclipse.osgi.framework.console.CommandInterpreter;
+import org.eclipse.osgi.framework.console.CommandProvider;
+
+import org.osgi.framework.BundleContext;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * @author Eike Stepper
+ */
+public class CDOCommandProvider implements CommandProvider
+{
+  private static final String INDENT = "  ";
+
+  public CDOCommandProvider(BundleContext bundleContext)
+  {
+    bundleContext.registerService(CommandProvider.class.getName(), this, null);
+  }
+
+  public String getHelp()
+  {
+    StringBuffer buffer = new StringBuffer();
+    buffer.append("---CDO commands---\n");
+    buffer.append("\tcdo list - list all active repositories\n");
+    buffer.append("\tcdo start - start repositories from a config file\n");
+    buffer.append("\tcdo stop - stop a repository\n");
+    buffer.append("\tcdo export - export the contents of a repository to an XML file\n");
+    buffer.append("\tcdo import - import the contents of a repository from an XML file\n");
+    buffer.append("\tcdo sessions - dump the sessions of a repository\n");
+    buffer.append("\tcdo packages - dump the packages of a repository\n");
+    buffer.append("\tcdo branches - dump the branches of a repository\n");
+    buffer.append("\tcdo locks - dump the durable locking areas of a repository\n");
+    buffer.append("\tcdo deletelocks - delete a durable locking area of a repository\n");
+    return buffer.toString();
+  }
+
+  public Object _cdo(CommandInterpreter interpreter)
+  {
+    try
+    {
+      String cmd = interpreter.nextArgument();
+      if ("list".equals(cmd))
+      {
+        list(interpreter);
+        return null;
+      }
+
+      if ("start".equals(cmd))
+      {
+        start(interpreter);
+        return null;
+      }
+
+      if ("stop".equals(cmd))
+      {
+        stop(interpreter);
+        return null;
+      }
+
+      if ("export".equals(cmd))
+      {
+        exportXML(interpreter);
+        return null;
+      }
+
+      if ("import".equals(cmd))
+      {
+        importXML(interpreter);
+        return null;
+      }
+
+      if ("sessions".equals(cmd))
+      {
+        sessions(interpreter);
+        return null;
+      }
+
+      if ("packages".equals(cmd))
+      {
+        packages(interpreter);
+        return null;
+      }
+
+      if ("branches".equals(cmd))
+      {
+        branches(interpreter);
+        return null;
+      }
+
+      if ("locks".equals(cmd))
+      {
+        locks(interpreter);
+        return null;
+      }
+
+      if ("deletelocks".equals(cmd))
+      {
+        deleteLocks(interpreter);
+        return null;
+      }
+
+      interpreter.println(getHelp());
+    }
+    catch (CommandException ex)
+    {
+      interpreter.println(ex.getMessage());
+    }
+    catch (Exception ex)
+    {
+      interpreter.printStackTrace(ex);
+    }
+
+    return null;
+  }
+
+  protected void list(CommandInterpreter interpreter) throws Exception
+  {
+    IManagedContainer container = CDOServerApplication.getContainer();
+    for (Object element : container.getElements(RepositoryFactory.PRODUCT_GROUP))
+    {
+      if (element instanceof InternalRepository)
+      {
+        InternalRepository repository = (InternalRepository)element;
+        interpreter.println(repository.getName());
+      }
+    }
+  }
+
+  protected void start(CommandInterpreter interpreter) throws Exception
+  {
+    String configFile = nextArgument(interpreter, "Syntax: cdo start <config-file>");
+
+    IManagedContainer container = CDOServerApplication.getContainer();
+    RepositoryConfigurator repositoryConfigurator = new RepositoryConfigurator(container);
+    IRepository[] repositories = repositoryConfigurator.configure(new File(configFile));
+
+    interpreter.println("Repositories started:");
+    if (repositories != null)
+    {
+      for (IRepository repository : repositories)
+      {
+        interpreter.println(repository.getName());
+      }
+    }
+  }
+
+  protected void stop(CommandInterpreter interpreter) throws Exception
+  {
+    InternalRepository repository = getRepository(interpreter, "Syntax: cdo stop <repository-name>");
+    LifecycleUtil.deactivate(repository);
+    interpreter.println("Repository stopped");
+  }
+
+  protected void exportXML(CommandInterpreter interpreter) throws Exception
+  {
+    String syntax = "Syntax: cdo export <repository-name> <export-file>";
+    InternalRepository repository = getRepository(interpreter, syntax);
+    String exportFile = nextArgument(interpreter, syntax);
+    OutputStream out = null;
+
+    try
+    {
+      out = new FileOutputStream(exportFile);
+
+      CDOServerExporter.XML exporter = new CDOServerExporter.XML(repository);
+      exporter.exportRepository(out);
+      interpreter.println("Repository exported");
+    }
+    finally
+    {
+      IOUtil.close(out);
+    }
+  }
+
+  protected void importXML(CommandInterpreter interpreter) throws Exception
+  {
+    String syntax = "Syntax: cdo import <repository-name> <import-file>";
+    InternalRepository repository = getRepository(interpreter, syntax);
+    String importFile = nextArgument(interpreter, syntax);
+    InputStream in = null;
+
+    try
+    {
+      in = new FileInputStream(importFile);
+      LifecycleUtil.deactivate(repository);
+
+      CDOServerImporter.XML importer = new CDOServerImporter.XML(repository);
+      importer.importRepository(in);
+
+      IManagedContainer container = CDOServerApplication.getContainer();
+      CDOServerUtil.addRepository(container, repository);
+
+      interpreter.println("Repository imported");
+    }
+    finally
+    {
+      IOUtil.close(in);
+    }
+  }
+
+  protected void sessions(CommandInterpreter interpreter)
+  {
+    InternalRepository repository = getRepository(interpreter, "Syntax: cdo sessions <repository-name>");
+    InternalSessionManager sessionManager = repository.getSessionManager();
+    for (InternalSession session : sessionManager.getSessions())
+    {
+      interpreter.println(session);
+      for (InternalView view : session.getViews())
+      {
+        interpreter.println(INDENT + view);
+      }
+    }
+  }
+
+  protected void packages(CommandInterpreter interpreter)
+  {
+    InternalRepository repository = getRepository(interpreter, "Syntax: cdo packages <repository-name>");
+    InternalCDOPackageRegistry packageRegistry = repository.getPackageRegistry(false);
+    for (InternalCDOPackageUnit packageUnit : packageRegistry.getPackageUnits())
+    {
+      interpreter.println(packageUnit);
+      for (InternalCDOPackageInfo packageInfo : packageUnit.getPackageInfos())
+      {
+        interpreter.println(INDENT + packageInfo);
+      }
+    }
+  }
+
+  protected void branches(CommandInterpreter interpreter)
+  {
+    InternalRepository repository = getRepository(interpreter, "Syntax: cdo branches <repository-name>");
+    branches(interpreter, repository.getBranchManager().getMainBranch(), "");
+  }
+
+  protected void locks(final CommandInterpreter interpreter)
+  {
+    final InternalRepository repository = getRepository(interpreter,
+        "Syntax: cdo locks <repository-name> [<username-prefix>]");
+    final String userIDPrefix = nextArgument(interpreter, null);
+
+    new WithAccessor()
+    {
+      @Override
+      protected void doExecute(IStoreAccessor accessor)
+      {
+        repository.getLockManager().getLockAreas(userIDPrefix, new IDurableLockingManager.LockArea.Handler()
+        {
+          public boolean handleLockArea(LockArea area)
+          {
+            interpreter.println(area.getDurableLockingID());
+            interpreter.println(INDENT + "userID = " + area.getUserID());
+            interpreter.println(INDENT + "branch = " + area.getBranch());
+            interpreter.println(INDENT + "timeStamp = " + CDOCommonUtil.formatTimeStamp(area.getTimeStamp()));
+            interpreter.println(INDENT + "readOnly = " + area.isReadOnly());
+            interpreter.println(INDENT + "locks = " + area.getLocks());
+            return true;
+          }
+        });
+      }
+    }.execute(repository);
+  }
+
+  protected void deleteLocks(CommandInterpreter interpreter)
+  {
+    String syntax = "Syntax: cdo deletelocks <repository-name> <area-id>";
+    final InternalRepository repository = getRepository(interpreter, syntax);
+    final String durableLockingID = nextArgument(interpreter, syntax);
+
+    new WithAccessor()
+    {
+      @Override
+      protected void doExecute(IStoreAccessor accessor)
+      {
+        repository.getLockManager().deleteLockArea(durableLockingID);
+      }
+    }.execute(repository);
+  }
+
+  private void branches(CommandInterpreter interpreter, InternalCDOBranch branch, String prefix)
+  {
+    interpreter.println(prefix + branch);
+    prefix += INDENT;
+    for (InternalCDOBranch child : branch.getBranches())
+    {
+      branches(interpreter, child, prefix);
+    }
+  }
+
+  private String nextArgument(CommandInterpreter interpreter, String syntax)
+  {
+    String argument = interpreter.nextArgument();
+    if (argument == null && syntax != null)
+    {
+      throw new CommandException(syntax);
+    }
+
+    return argument;
+  }
+
+  private InternalRepository getRepository(CommandInterpreter interpreter, String syntax)
+  {
+    String repositoryName = nextArgument(interpreter, syntax);
+    InternalRepository repository = getRepository(repositoryName);
+    if (repository == null)
+    {
+      throw new CommandException("Repository not found: " + repositoryName);
+    }
+
+    return repository;
+  }
+
+  private InternalRepository getRepository(String name)
+  {
+    IManagedContainer container = CDOServerApplication.getContainer();
+    for (Object element : container.getElements(RepositoryFactory.PRODUCT_GROUP))
+    {
+      if (element instanceof InternalRepository)
+      {
+        InternalRepository repository = (InternalRepository)element;
+        if (repository.getName().equals(name))
+        {
+          return repository;
+        }
+      }
+    }
+
+    return null;
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  protected static abstract class WithAccessor
+  {
+    public void execute(InternalRepository repository)
+    {
+      IStoreAccessor accessor = repository.getStore().getReader(null);
+      StoreThreadLocal.setAccessor(accessor);
+
+      try
+      {
+        doExecute(accessor);
+      }
+      finally
+      {
+        StoreThreadLocal.release();
+      }
+    }
+
+    protected abstract void doExecute(IStoreAccessor accessor);
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  private static final class CommandException extends RuntimeException
+  {
+    private static final long serialVersionUID = 1L;
+
+    public CommandException(String message)
+    {
+      super(message);
+    }
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/bundle/CDOServerApplication.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/bundle/CDOServerApplication.java
new file mode 100644
index 0000000..deebb36
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/bundle/CDOServerApplication.java
@@ -0,0 +1,137 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.internal.server.bundle;
+
+import org.eclipse.emf.cdo.internal.server.messages.Messages;
+import org.eclipse.emf.cdo.server.IRepository;
+import org.eclipse.emf.cdo.spi.server.IAppExtension;
+import org.eclipse.emf.cdo.spi.server.RepositoryConfigurator;
+
+import org.eclipse.net4j.util.container.IManagedContainer;
+import org.eclipse.net4j.util.container.IPluginContainer;
+import org.eclipse.net4j.util.lifecycle.LifecycleUtil;
+import org.eclipse.net4j.util.om.OMPlatform;
+import org.eclipse.net4j.util.om.OSGiApplication;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.Platform;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Eike Stepper
+ */
+public class CDOServerApplication extends OSGiApplication
+{
+  public static final String ID = OM.BUNDLE_ID + ".app"; //$NON-NLS-1$
+
+  public static final String PROP_BROWSER_PORT = "org.eclipse.emf.cdo.server.browser.port"; //$NON-NLS-1$
+
+  private IRepository[] repositories;
+
+  private List<IAppExtension> extensions = new ArrayList<IAppExtension>();
+
+  public CDOServerApplication()
+  {
+    super(ID);
+  }
+
+  @Override
+  protected void doStart() throws Exception
+  {
+    super.doStart();
+    IManagedContainer container = getContainer();
+
+    OM.LOG.info(Messages.getString("CDOServerApplication.1")); //$NON-NLS-1$
+    File configFile = OMPlatform.INSTANCE.getConfigFile("cdo-server.xml"); //$NON-NLS-1$
+    if (configFile != null && configFile.exists())
+    {
+      RepositoryConfigurator repositoryConfigurator = new RepositoryConfigurator(container);
+      repositories = repositoryConfigurator.configure(configFile);
+      if (repositories == null || repositories.length == 0)
+      {
+        OM.LOG.warn(Messages.getString("CDOServerApplication.3") + " " + configFile.getAbsolutePath()); //$NON-NLS-1$
+      }
+
+      String port = OMPlatform.INSTANCE.getProperty(PROP_BROWSER_PORT);
+      if (port != null)
+      {
+        container.getElement("org.eclipse.emf.cdo.server.browsers", "default", port); //$NON-NLS-1$ //$NON-NLS-2$
+      }
+
+      startExtensions(configFile);
+    }
+    else
+    {
+      OM.LOG.warn(Messages.getString("CDOServerApplication.5") + " " + configFile.getAbsolutePath()); //$NON-NLS-1$
+    }
+
+    OM.LOG.info(Messages.getString("CDOServerApplication.6")); //$NON-NLS-1$
+  }
+
+  @Override
+  protected void doStop() throws Exception
+  {
+    OM.LOG.info(Messages.getString("CDOServerApplication.7")); //$NON-NLS-1$
+    for (IAppExtension extension : extensions)
+    {
+      try
+      {
+        extension.stop();
+      }
+      catch (Exception ex)
+      {
+        OM.LOG.error(ex);
+      }
+    }
+
+    if (repositories != null)
+    {
+      for (IRepository repository : repositories)
+      {
+        LifecycleUtil.deactivate(repository);
+      }
+    }
+
+    OM.LOG.info(Messages.getString("CDOServerApplication.8")); //$NON-NLS-1$
+    super.doStop();
+  }
+
+  private void startExtensions(File configFile)
+  {
+    IExtensionRegistry registry = Platform.getExtensionRegistry();
+    IConfigurationElement[] elements = registry.getConfigurationElementsFor(OM.BUNDLE_ID, IAppExtension.EXT_POINT);
+    for (final IConfigurationElement element : elements)
+    {
+      if ("appExtension".equals(element.getName())) //$NON-NLS-1$
+      {
+        try
+        {
+          IAppExtension extension = (IAppExtension)element.createExecutableExtension("class"); //$NON-NLS-1$
+          extension.start(configFile);
+          extensions.add(extension);
+        }
+        catch (Exception ex)
+        {
+          OM.LOG.error(ex);
+        }
+      }
+    }
+  }
+
+  public static IManagedContainer getContainer()
+  {
+    return IPluginContainer.INSTANCE;
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/bundle/OM.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/bundle/OM.java
new file mode 100644
index 0000000..245e61b
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/bundle/OM.java
@@ -0,0 +1,66 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.internal.server.bundle;
+
+import org.eclipse.net4j.util.om.OMBundle;
+import org.eclipse.net4j.util.om.OMPlatform;
+import org.eclipse.net4j.util.om.OSGiActivator;
+import org.eclipse.net4j.util.om.log.OMLogger;
+import org.eclipse.net4j.util.om.trace.OMTracer;
+
+/**
+ * The <em>Operations & Maintenance</em> class of this bundle.
+ * 
+ * @author Eike Stepper
+ */
+public abstract class OM
+{
+  public static final String BUNDLE_ID = "org.eclipse.emf.cdo.server"; //$NON-NLS-1$
+
+  public static final OMBundle BUNDLE = OMPlatform.INSTANCE.bundle(BUNDLE_ID, OM.class);
+
+  public static final OMTracer DEBUG = BUNDLE.tracer("debug"); //$NON-NLS-1$
+
+  public static final OMTracer DEBUG_PROTOCOL = DEBUG.tracer("protocol"); //$NON-NLS-1$
+
+  public static final OMTracer DEBUG_REPOSITORY = DEBUG.tracer("repository"); //$NON-NLS-1$
+
+  public static final OMTracer DEBUG_SESSION = DEBUG.tracer("session"); //$NON-NLS-1$
+
+  public static final OMTracer DEBUG_TRANSACTION = DEBUG.tracer("transaction"); //$NON-NLS-1$
+
+  public static final OMTracer DEBUG_REVISION = DEBUG.tracer("revision"); //$NON-NLS-1$
+
+  public static final OMTracer DEBUG_RESOURCE = DEBUG.tracer("resource"); //$NON-NLS-1$
+
+  public static final OMTracer DEBUG_STORE = DEBUG.tracer("store"); //$NON-NLS-1$
+
+  public static final OMTracer DEBUG_TYPES = DEBUG.tracer("types"); //$NON-NLS-1$
+
+  public static final OMLogger LOG = BUNDLE.logger();
+
+  /**
+   * @author Eike Stepper
+   */
+  public static final class Activator extends OSGiActivator
+  {
+    public Activator()
+    {
+      super(BUNDLE);
+    }
+
+    @Override
+    protected void doStart() throws Exception
+    {
+      new CDOCommandProvider(bundleContext);
+    }
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/embedded/EmbeddedClientSession.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/embedded/EmbeddedClientSession.java
new file mode 100644
index 0000000..0552041
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/embedded/EmbeddedClientSession.java
@@ -0,0 +1,98 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Andre Dietisheim - bug 256649
+ */
+package org.eclipse.emf.cdo.internal.server.embedded;
+
+import org.eclipse.emf.cdo.common.lob.CDOLobStore;
+import org.eclipse.emf.cdo.common.revision.CDORevisionCache;
+import org.eclipse.emf.cdo.common.revision.CDORevisionUtil;
+import org.eclipse.emf.cdo.internal.server.embedded.EmbeddedClientSessionConfiguration.RepositoryInfo;
+import org.eclipse.emf.cdo.server.embedded.CDOSession;
+import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranchManager;
+import org.eclipse.emf.cdo.spi.common.commit.InternalCDOCommitInfoManager;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager;
+import org.eclipse.emf.cdo.spi.server.InternalRepository;
+
+import org.eclipse.emf.internal.cdo.session.CDOSessionImpl;
+
+/**
+ * @author Eike Stepper
+ */
+public class EmbeddedClientSession extends CDOSessionImpl implements CDOSession
+{
+  private InternalRepository repository;
+
+  public EmbeddedClientSession()
+  {
+  }
+
+  public InternalRepository getRepository()
+  {
+    return repository;
+  }
+
+  @Override
+  public InternalCDOPackageRegistry getPackageRegistry()
+  {
+    return getRepository().getPackageRegistry();
+  }
+
+  @Override
+  public InternalCDOBranchManager getBranchManager()
+  {
+    return getRepository().getBranchManager();
+  }
+
+  @Override
+  public InternalCDOCommitInfoManager getCommitInfoManager()
+  {
+    return getRepository().getCommitInfoManager();
+  }
+
+  @Override
+  public CDOLobStore getLobStore()
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  protected void doActivate() throws Exception
+  {
+    super.doActivate();
+
+    EmbeddedClientSessionProtocol protocol = new EmbeddedClientSessionProtocol(this);
+    setSessionProtocol(protocol);
+    protocol.activate();
+    protocol.openSession(options().isPassiveUpdateEnabled());
+
+    setLastUpdateTime(repository.getLastCommitTimeStamp());
+    setRepositoryInfo(new RepositoryInfo(this));
+
+    InternalCDORevisionManager revisionManager = (InternalCDORevisionManager)CDORevisionUtil.createRevisionManager();
+    setRevisionManager(revisionManager);
+    revisionManager.setSupportingAudits(getRepositoryInfo().isSupportingAudits());
+    revisionManager.setSupportingBranches(getRepositoryInfo().isSupportingBranches());
+    revisionManager.setCache(CDORevisionCache.NOOP);
+    revisionManager.setRevisionLoader(getSessionProtocol());
+    revisionManager.setRevisionLocker(this);
+    revisionManager.activate();
+  }
+
+  @Override
+  protected void doDeactivate() throws Exception
+  {
+    super.doDeactivate();
+
+    getRevisionManager().deactivate();
+    setRevisionManager(null);
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/embedded/EmbeddedClientSessionConfiguration.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/embedded/EmbeddedClientSessionConfiguration.java
new file mode 100644
index 0000000..3870610
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/embedded/EmbeddedClientSessionConfiguration.java
@@ -0,0 +1,153 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.internal.server.embedded;
+
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.id.CDOID.ObjectType;
+import org.eclipse.emf.cdo.server.IRepository;
+import org.eclipse.emf.cdo.server.embedded.CDOSessionConfiguration;
+import org.eclipse.emf.cdo.spi.server.InternalRepository;
+
+import org.eclipse.emf.internal.cdo.session.CDOSessionConfigurationImpl;
+
+import org.eclipse.net4j.util.CheckUtil;
+
+import org.eclipse.emf.spi.cdo.InternalCDOSession;
+
+import java.util.Set;
+
+/**
+ * @author Eike Stepper
+ */
+public class EmbeddedClientSessionConfiguration extends CDOSessionConfigurationImpl implements CDOSessionConfiguration
+{
+  private InternalRepository repository;
+
+  public EmbeddedClientSessionConfiguration()
+  {
+    throw new UnsupportedOperationException("Embedded sessions are not yet supported");
+  }
+
+  public InternalRepository getRepository()
+  {
+    return repository;
+  }
+
+  public void setRepository(IRepository repository)
+  {
+    checkNotOpen();
+    this.repository = (InternalRepository)repository;
+  }
+
+  @Override
+  public org.eclipse.emf.cdo.server.embedded.CDOSession openSession()
+  {
+    return (org.eclipse.emf.cdo.server.embedded.CDOSession)super.openSession();
+  }
+
+  public InternalCDOSession createSession()
+  {
+    if (isActivateOnOpen())
+    {
+      CheckUtil.checkState(repository, "Specify a repository"); //$NON-NLS-1$
+    }
+
+    return new EmbeddedClientSession();
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  protected static class RepositoryInfo implements org.eclipse.emf.cdo.session.CDORepositoryInfo
+  {
+    private EmbeddedClientSession session;
+
+    public RepositoryInfo(EmbeddedClientSession session)
+    {
+      this.session = session;
+    }
+
+    public String getName()
+    {
+      return session.getRepository().getName();
+    }
+
+    public String getUUID()
+    {
+      return session.getRepository().getUUID();
+    }
+
+    public Type getType()
+    {
+      return session.getRepository().getType();
+    }
+
+    public State getState()
+    {
+      return session.getRepository().getState();
+    }
+
+    public long getCreationTime()
+    {
+      return session.getRepository().getCreationTime();
+    }
+
+    public long getTimeStamp()
+    {
+      return getTimeStamp(false);
+    }
+
+    public long getTimeStamp(boolean forceRefresh)
+    {
+      return System.currentTimeMillis();
+    }
+
+    public CDOID getRootResourceID()
+    {
+      return session.getRepository().getRootResourceID();
+    }
+
+    public boolean isSupportingAudits()
+    {
+      return session.getRepository().isSupportingAudits();
+    }
+
+    public boolean isSupportingBranches()
+    {
+      return session.getRepository().isSupportingBranches();
+    }
+
+    public boolean isSupportingEcore()
+    {
+      return session.getRepository().isSupportingEcore();
+    }
+
+    public boolean isEnsuringReferentialIntegrity()
+    {
+      return session.getRepository().isEnsuringReferentialIntegrity();
+    }
+
+    public IDGenerationLocation getIDGenerationLocation()
+    {
+      return session.getRepository().getIDGenerationLocation();
+    }
+
+    public String getStoreType()
+    {
+      return session.getRepository().getStoreType();
+    }
+
+    public Set<ObjectType> getObjectIDTypes()
+    {
+      return session.getRepository().getObjectIDTypes();
+    }
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/embedded/EmbeddedClientSessionProtocol.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/embedded/EmbeddedClientSessionProtocol.java
new file mode 100644
index 0000000..531f5a9
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/embedded/EmbeddedClientSessionProtocol.java
@@ -0,0 +1,584 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.internal.server.embedded;
+
+import org.eclipse.emf.cdo.CDOObject;
+import org.eclipse.emf.cdo.common.CDOCommonSession.Options.LockNotificationMode;
+import org.eclipse.emf.cdo.common.CDOCommonSession.Options.PassiveUpdateMode;
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchHandler;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPointRange;
+import org.eclipse.emf.cdo.common.branch.CDOBranchVersion;
+import org.eclipse.emf.cdo.common.commit.CDOChangeSetData;
+import org.eclipse.emf.cdo.common.commit.CDOCommitData;
+import org.eclipse.emf.cdo.common.commit.CDOCommitInfoHandler;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.id.CDOIDProvider;
+import org.eclipse.emf.cdo.common.lob.CDOLob;
+import org.eclipse.emf.cdo.common.lob.CDOLobInfo;
+import org.eclipse.emf.cdo.common.lock.CDOLockState;
+import org.eclipse.emf.cdo.common.model.CDOPackageUnit;
+import org.eclipse.emf.cdo.common.protocol.CDOAuthenticator;
+import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion;
+import org.eclipse.emf.cdo.common.revision.CDORevisionHandler;
+import org.eclipse.emf.cdo.common.revision.CDORevisionKey;
+import org.eclipse.emf.cdo.common.util.CDOQueryQueue;
+import org.eclipse.emf.cdo.server.StoreThreadLocal;
+import org.eclipse.emf.cdo.session.remote.CDORemoteSession;
+import org.eclipse.emf.cdo.session.remote.CDORemoteSessionMessage;
+import org.eclipse.emf.cdo.spi.common.CDOAuthenticationResult;
+import org.eclipse.emf.cdo.spi.common.CDORawReplicationContext;
+import org.eclipse.emf.cdo.spi.common.CDOReplicationContext;
+import org.eclipse.emf.cdo.spi.common.commit.CDORevisionAvailabilityInfo;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionDelta;
+import org.eclipse.emf.cdo.spi.common.revision.RevisionInfo;
+import org.eclipse.emf.cdo.spi.server.InternalCommitContext;
+import org.eclipse.emf.cdo.spi.server.InternalQueryManager;
+import org.eclipse.emf.cdo.spi.server.InternalQueryResult;
+import org.eclipse.emf.cdo.spi.server.InternalRepository;
+import org.eclipse.emf.cdo.spi.server.InternalSession;
+import org.eclipse.emf.cdo.spi.server.InternalTransaction;
+import org.eclipse.emf.cdo.spi.server.InternalView;
+import org.eclipse.emf.cdo.view.CDOView;
+
+import org.eclipse.net4j.util.collection.Pair;
+import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
+import org.eclipse.net4j.util.lifecycle.Lifecycle;
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.spi.cdo.AbstractQueryIterator;
+import org.eclipse.emf.spi.cdo.CDOSessionProtocol;
+import org.eclipse.emf.spi.cdo.InternalCDOObject;
+import org.eclipse.emf.spi.cdo.InternalCDORemoteSessionManager;
+import org.eclipse.emf.spi.cdo.InternalCDOXATransaction.InternalCDOXACommitContext;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author Eike Stepper
+ */
+public class EmbeddedClientSessionProtocol extends Lifecycle implements CDOSessionProtocol
+{
+  private EmbeddedClientSession session;
+
+  // A separate session protocol instance is required because the getSession() methods are ambiguous!
+  private EmbeddedServerSessionProtocol serverSessionProtocol;
+
+  private InternalRepository repository;
+
+  public EmbeddedClientSessionProtocol(EmbeddedClientSession session)
+  {
+    this.session = session;
+  }
+
+  public EmbeddedClientSession getSession()
+  {
+    return session;
+  }
+
+  public EmbeddedServerSessionProtocol getServerSessionProtocol()
+  {
+    return serverSessionProtocol;
+  }
+
+  public InternalSession openSession(boolean passiveUpdateEnabled)
+  {
+    repository = session.getRepository();
+    activate();
+    return serverSessionProtocol.openSession(repository, passiveUpdateEnabled);
+  }
+
+  public EPackage[] loadPackages(CDOPackageUnit packageUnit)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public Pair<Integer, Long> createBranch(int branchID, BranchInfo branchInfo)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public BranchInfo loadBranch(int branchID)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public SubBranchInfo[] loadSubBranches(int branchID)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public int loadBranches(int startID, int endID, CDOBranchHandler branchHandler)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public RepositoryTimeResult getRepositoryTime()
+  {
+    RepositoryTimeResult result = new RepositoryTimeResult();
+    long timeStamp = System.currentTimeMillis();
+    result.setRequested(timeStamp);
+    result.setIndicated(timeStamp);
+    result.setResponded(timeStamp);
+    result.setConfirmed(timeStamp);
+    return result;
+  }
+
+  public CDOLockState[] getLockStates(int viewID, Collection<CDOID> ids)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public void enableLockNotifications(int viewID, boolean enable)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public void disablePassiveUpdate()
+  {
+    // serverSessionProtocol.getSession().setPassiveUpdateEnabled(passiveUpdateEnabled);
+    // TODO: implement EmbeddedClientSessionProtocol.setPassiveUpdate(idAndVersions, initialChunkSize,
+    // passiveUpdateEnabled)
+    throw new UnsupportedOperationException();
+  }
+
+  public void setPassiveUpdateMode(PassiveUpdateMode mode)
+  {
+    // TODO: implement EmbeddedClientSessionProtocol.setPassiveUpdateMode(mode)
+    throw new UnsupportedOperationException();
+  }
+
+  public void setLockNotificationMode(LockNotificationMode mode)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object loadChunk(InternalCDORevision revision, EStructuralFeature feature, int accessIndex, int fetchIndex,
+      int fromIndex, int toIndex)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public void loadCommitInfos(CDOBranch branch, long startTime, long endTime, CDOCommitInfoHandler handler)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public CDOCommitData loadCommitData(long timeStamp)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public InternalCDORevision loadRevisionByVersion(CDOID id, CDOBranchVersion branchVersion, int referenceChunk)
+  {
+    try
+    {
+      InternalSession session = serverSessionProtocol.getSession();
+      StoreThreadLocal.setSession(session);
+      return repository.getRevisionManager().getRevisionByVersion(id, branchVersion, referenceChunk, true);
+    }
+    finally
+    {
+      StoreThreadLocal.release();
+    }
+  }
+
+  public List<InternalCDORevision> loadRevisions(List<RevisionInfo> infos, CDOBranchPoint branchPoint,
+      int referenceChunk, int prefetchDepth)
+  {
+    try
+    {
+      InternalSession session = serverSessionProtocol.getSession();
+      StoreThreadLocal.setSession(session);
+
+      List<CDOID> ids = new ArrayList<CDOID>(infos.size());
+      for (RevisionInfo info : infos)
+      {
+        ids.add(info.getID());
+      }
+
+      // @SuppressWarnings("unchecked")
+      // List<InternalCDORevision> revisions = (List<InternalCDORevision>)(List<?>)repository.getRevisionManager()
+      // .getRevisions(ids, branchPoint, referenceChunk, prefetchDepth, true);
+
+      // TODO: implement EmbeddedClientSessionProtocol.loadRevisions(infos, branchPoint, referenceChunk, prefetchDepth)
+      throw new UnsupportedOperationException();
+    }
+    finally
+    {
+      StoreThreadLocal.release();
+    }
+  }
+
+  public RefreshSessionResult refresh(long lastUpdateTime,
+      Map<CDOBranch, Map<CDOID, InternalCDORevision>> viewedRevisions, int initialChunkSize,
+      boolean enablePassiveUpdates)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public void openView(int viewID, boolean readOnly, CDOBranchPoint branchPoint)
+  {
+    InternalSession session = serverSessionProtocol.getSession();
+    if (readOnly)
+    {
+      session.openView(viewID, branchPoint);
+    }
+    else
+    {
+      session.openTransaction(viewID, branchPoint);
+    }
+  }
+
+  public CDOBranchPoint openView(int viewID, boolean readOnly, String durableLockingID)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public void switchTarget(int viewID, CDOBranchPoint branchPoint, List<InternalCDOObject> invalidObjects,
+      List<CDORevisionKey> allChangedObjects, List<CDOIDAndVersion> allDetachedObjects, OMMonitor monitor)
+  {
+    // TODO: implement EmbeddedClientSessionProtocol.changeView(viewID, branchPoint, invalidObjects, allChangedObjects,
+    // allDetachedObjects, monitor)
+    throw new UnsupportedOperationException();
+
+    // try
+    // {
+    // monitor.begin();
+    // Async async = monitor.forkAsync();
+    //
+    // try
+    // {
+    // InternalView view = serverSessionProtocol.getSession().getView(viewID);
+    // if (view != null)
+    // {
+    // List<CDOID> ids = new ArrayList<CDOID>(invalidObjects.size());
+    // for (InternalCDOObject object : invalidObjects)
+    // {
+    // ids.add(object.cdoID());
+    // }
+    //
+    // view.changeTarget(branchPoint, ids, allChangedObjects, allDetachedObjects);
+    // }
+    // }
+    // finally
+    // {
+    // async.stop();
+    // }
+    // }
+    // finally
+    // {
+    // monitor.done();
+    // }
+  }
+
+  public void closeView(int viewID)
+  {
+    InternalView view = serverSessionProtocol.getSession().getView(viewID);
+    if (view != null)
+    {
+      view.close();
+    }
+  }
+
+  public void changeSubscription(int viewID, List<CDOID> ids, boolean subscribeMode, boolean clear)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public void query(CDOView view, AbstractQueryIterator<?> query)
+  {
+    InternalView serverView = serverSessionProtocol.getSession().getView(view.getViewID());
+    InternalQueryManager queryManager = repository.getQueryManager();
+    InternalQueryResult result = queryManager.execute(serverView, query.getQueryInfo());
+
+    query.setQueryID(result.getQueryID());
+    CDOQueryQueue<Object> resultQueue = query.getQueue();
+
+    try
+    {
+      while (result.hasNext())
+      {
+        Object object = result.next();
+        resultQueue.add(object);
+      }
+    }
+    catch (RuntimeException ex)
+    {
+      resultQueue.setException(ex);
+    }
+    catch (Throwable throwable)
+    {
+      resultQueue.setException(new RuntimeException(throwable.getMessage(), throwable));
+    }
+    finally
+    {
+      resultQueue.close();
+    }
+  }
+
+  public boolean cancelQuery(int queryID)
+  {
+    repository.getQueryManager().cancel(queryID);
+    return true;
+  }
+
+  public boolean isObjectLocked(CDOView view, CDOObject object, LockType lockType, boolean byOthers)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  @Deprecated
+  public LockObjectsResult lockObjects(List<InternalCDORevision> viewedRevisions, int viewID, CDOBranch viewedBranch,
+      LockType lockType, long timeout) throws InterruptedException
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * @since 4.1
+   */
+  public LockObjectsResult lockObjects2(List<CDORevisionKey> revisionKeys, int viewID, CDOBranch viewedBranch,
+      LockType lockType, long timeout) throws InterruptedException
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public void unlockObjects(CDOView view, Collection<CDOID> objectIDs, LockType lockType)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public UnlockObjectsResult unlockObjects2(CDOView view, Collection<CDOID> objectIDs, LockType lockType)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public LockObjectsResult delegateLockObjects(String lockAreaID, List<CDORevisionKey> revisionKeys,
+      CDOBranch viewedBranch, LockType lockType, long timeout) throws InterruptedException
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public UnlockObjectsResult delegateUnlockObjects(String lockAreaID, Collection<CDOID> objectIDs, LockType lockType)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public String changeLockArea(CDOView view, boolean create)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public List<byte[]> queryLobs(Set<byte[]> ids)
+  {
+    // TODO: implement EmbeddedClientSessionProtocol.queryLobs(ids)
+    throw new UnsupportedOperationException();
+  }
+
+  public void loadLob(CDOLobInfo info, Object outputStreamOrWriter)
+  {
+    // TODO: implement EmbeddedClientSessionProtocol.loadLob(info, out)
+    throw new UnsupportedOperationException();
+  }
+
+  public void handleRevisions(EClass eClass, CDOBranch branch, boolean exactBranch, long timeStamp, boolean exactTime,
+      CDORevisionHandler handler)
+  {
+    // TODO: implement EmbeddedClientSessionProtocol.handleRevisions(eClass, branch, exactBranch, timeStamp, exactTime,
+    // handler)
+    throw new UnsupportedOperationException();
+  }
+
+  public CommitTransactionResult commitTransaction(int transactionID, String comment, boolean releaseLocks,
+      CDOIDProvider idProvider, CDOCommitData commitData, Collection<CDOLob<?>> lobs, OMMonitor monitor)
+  {
+    monitor.begin(2);
+    boolean success = false;
+    InternalCommitContext serverCommitContext = null;
+    CommitTransactionResult result = null;
+
+    try
+    {
+      InternalTransaction serverTransaction = (InternalTransaction)serverSessionProtocol.getSession().getView(
+          transactionID);
+      serverCommitContext = serverTransaction.createCommitContext();
+      serverCommitContext.preWrite();
+      serverCommitContext.setAutoReleaseLocksEnabled(releaseLocks);
+
+      List<CDOPackageUnit> npu = commitData.getNewPackageUnits();
+      serverCommitContext.setNewPackageUnits(npu.toArray(new InternalCDOPackageUnit[npu.size()]));
+
+      List<CDOIDAndVersion> no = commitData.getNewObjects();
+      InternalCDORevision[] array = new InternalCDORevision[no.size()];
+      int index = 0;
+      for (CDOIDAndVersion object : no)
+      {
+        InternalCDORevision revision = (InternalCDORevision)object;
+        // revision.convertEObjects(clientTransaction);
+        array[index++] = revision;
+      }
+
+      serverCommitContext.setNewObjects(array);
+
+      List<CDORevisionKey> rd = commitData.getChangedObjects();
+      serverCommitContext.setDirtyObjectDeltas(rd.toArray(new InternalCDORevisionDelta[rd.size()]));
+
+      List<CDOIDAndVersion> detachedObjects = commitData.getDetachedObjects();
+      serverCommitContext.setDetachedObjects(detachedObjects.toArray(new CDOID[detachedObjects.size()]));
+
+      serverCommitContext.write(monitor.fork());
+      success = serverCommitContext.getRollbackMessage() == null;
+      if (success)
+      {
+        serverCommitContext.commit(monitor.fork());
+      }
+      else
+      {
+        monitor.worked();
+      }
+
+      // result = new CommitTransactionResult(commitData, serverCommitContext.getBranchPoint().getTimeStamp());
+      // for (Entry<CDOID, CDOID> entry : serverCommitContext.getIDMappings().entrySet())
+      // {
+      // result.addIDMapping(entry.getKey(), entry.getValue());
+      // }
+    }
+    finally
+    {
+      if (serverCommitContext != null)
+      {
+        serverCommitContext.postCommit(success);
+      }
+
+      monitor.done();
+    }
+
+    return result;
+  }
+
+  public CommitTransactionResult commitDelegation(CDOBranch branch, String userID, String comment,
+      CDOCommitData commitData, Map<CDOID, EClass> detachedObjectTypes, Collection<CDOLob<?>> lobs, OMMonitor monitor)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public CommitTransactionResult commitXATransactionCancel(InternalCDOXACommitContext xaContext, OMMonitor monitor)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public CommitTransactionResult commitXATransactionPhase1(InternalCDOXACommitContext xaContext, OMMonitor monitor)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public CommitTransactionResult commitXATransactionPhase2(InternalCDOXACommitContext xaContext, OMMonitor monitor)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public CommitTransactionResult commitXATransactionPhase3(InternalCDOXACommitContext xaContext, OMMonitor monitor)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public List<CDORemoteSession> getRemoteSessions(InternalCDORemoteSessionManager manager, boolean subscribe)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public Set<Integer> sendRemoteMessage(CDORemoteSessionMessage message, List<CDORemoteSession> recipients)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean unsubscribeRemoteSessions()
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public void replicateRepository(CDOReplicationContext context, OMMonitor monitor)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public void replicateRepositoryRaw(CDORawReplicationContext context, OMMonitor monitor)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public CDOChangeSetData[] loadChangeSets(CDOBranchPointRange... ranges)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public Set<CDOID> loadMergeData(CDORevisionAvailabilityInfo targetInfo, CDORevisionAvailabilityInfo sourceInfo,
+      CDORevisionAvailabilityInfo targetBaseInfo, CDORevisionAvailabilityInfo sourceBaseInfo)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public CDOAuthenticationResult handleAuthenticationChallenge(byte[] randomToken) throws Exception
+  {
+    CDOAuthenticator authenticator = getSession().getAuthenticator();
+    if (authenticator == null)
+    {
+      throw new IllegalStateException("No authenticator configured"); //$NON-NLS-1$
+    }
+
+    CDOAuthenticationResult result = authenticator.authenticate(randomToken);
+    if (result == null)
+    {
+      throw new SecurityException("Not authenticated"); //$NON-NLS-1$
+    }
+
+    String userID = result.getUserID();
+    if (userID == null)
+    {
+      throw new SecurityException("No user ID"); //$NON-NLS-1$
+    }
+
+    byte[] cryptedToken = result.getCryptedToken();
+    if (cryptedToken == null)
+    {
+      throw new SecurityException("No crypted token"); //$NON-NLS-1$
+    }
+
+    return result;
+  }
+
+  @Override
+  protected void doActivate() throws Exception
+  {
+    super.doActivate();
+    serverSessionProtocol = new EmbeddedServerSessionProtocol(this);
+    serverSessionProtocol.activate();
+  }
+
+  @Override
+  protected void doDeactivate() throws Exception
+  {
+    serverSessionProtocol.deactivate();
+    serverSessionProtocol = null;
+    super.doDeactivate();
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/embedded/EmbeddedServerSessionProtocol.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/embedded/EmbeddedServerSessionProtocol.java
new file mode 100644
index 0000000..3dd8efa
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/embedded/EmbeddedServerSessionProtocol.java
@@ -0,0 +1,109 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.internal.server.embedded;
+
+import org.eclipse.emf.cdo.common.CDOCommonRepository;
+import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
+import org.eclipse.emf.cdo.session.remote.CDORemoteSessionMessage;
+import org.eclipse.emf.cdo.spi.common.CDOAuthenticationResult;
+import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranch;
+import org.eclipse.emf.cdo.spi.server.ISessionProtocol;
+import org.eclipse.emf.cdo.spi.server.InternalRepository;
+import org.eclipse.emf.cdo.spi.server.InternalSession;
+
+import org.eclipse.net4j.util.lifecycle.Lifecycle;
+
+/**
+ * @author Eike Stepper
+ */
+public class EmbeddedServerSessionProtocol extends Lifecycle implements ISessionProtocol
+{
+  // A separate session protocol instance is required because the getSession() methods are ambiguous!
+  private EmbeddedClientSessionProtocol clientSessionProtocol;
+
+  private InternalSession session;
+
+  public EmbeddedServerSessionProtocol(EmbeddedClientSessionProtocol clientSessionProtocol)
+  {
+    this.clientSessionProtocol = clientSessionProtocol;
+  }
+
+  public EmbeddedClientSessionProtocol getClientSessionProtocol()
+  {
+    return clientSessionProtocol;
+  }
+
+  public InternalSession openSession(InternalRepository repository, boolean passiveUpdateEnabled)
+  {
+    session = repository.getSessionManager().openSession(this);
+    session.setPassiveUpdateEnabled(passiveUpdateEnabled);
+    return session;
+  }
+
+  public InternalSession getSession()
+  {
+    return session;
+  }
+
+  public CDOAuthenticationResult sendAuthenticationChallenge(byte[] randomToken) throws Exception
+  {
+    return clientSessionProtocol.handleAuthenticationChallenge(randomToken);
+  }
+
+  public void sendRepositoryTypeNotification(CDOCommonRepository.Type oldType, CDOCommonRepository.Type newType)
+  {
+    EmbeddedClientSession clientSession = clientSessionProtocol.getSession();
+    clientSession.handleRepositoryTypeChanged(oldType, newType);
+  }
+
+  @Deprecated
+  public void sendRepositoryStateNotification(CDOCommonRepository.State oldState, CDOCommonRepository.State newState)
+  {
+    sendRepositoryStateNotification(oldState, newState, null);
+  }
+
+  public void sendRepositoryStateNotification(CDOCommonRepository.State oldState, CDOCommonRepository.State newState,
+      CDOID rootResourceID)
+  {
+    EmbeddedClientSession clientSession = clientSessionProtocol.getSession();
+    clientSession.handleRepositoryStateChanged(oldState, newState);
+  }
+
+  public void sendBranchNotification(InternalCDOBranch branch)
+  {
+    EmbeddedClientSession clientSession = clientSessionProtocol.getSession();
+    clientSession.handleBranchNotification(branch);
+  }
+
+  public void sendCommitNotification(CDOCommitInfo commitInfo)
+  {
+    EmbeddedClientSession clientSession = clientSessionProtocol.getSession();
+    clientSession.handleCommitNotification(commitInfo);
+  }
+
+  public void sendLockNotification(CDOLockChangeInfo lockChangeInfo)
+  {
+    EmbeddedClientSession clientSession = clientSessionProtocol.getSession();
+    clientSession.handleLockNotification(lockChangeInfo, null);
+  }
+
+  public void sendRemoteSessionNotification(InternalSession sender, byte opcode)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public void sendRemoteMessageNotification(InternalSession sender, CDORemoteSessionMessage message)
+  {
+    throw new UnsupportedOperationException();
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/mem/MEMStore.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/mem/MEMStore.java
new file mode 100644
index 0000000..96f26ac
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/mem/MEMStore.java
@@ -0,0 +1,1310 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Simon McDuff - initial API and implementation
+ *    Simon McDuff - bug 233273
+ *    Eike Stepper - maintenance
+ *    Andre Dietisheim - bug 256649
+ */
+package org.eclipse.emf.cdo.internal.server.mem;
+
+import org.eclipse.emf.cdo.common.CDOCommonRepository.IDGenerationLocation;
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchHandler;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.branch.CDOBranchVersion;
+import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
+import org.eclipse.emf.cdo.common.commit.CDOCommitInfoHandler;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.id.CDOIDUtil;
+import org.eclipse.emf.cdo.common.lob.CDOLobHandler;
+import org.eclipse.emf.cdo.common.lock.CDOLockUtil;
+import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockArea.Handler;
+import org.eclipse.emf.cdo.common.model.CDOModelConstants;
+import org.eclipse.emf.cdo.common.protocol.CDODataInput;
+import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionHandler;
+import org.eclipse.emf.cdo.common.util.CDOCommonUtil;
+import org.eclipse.emf.cdo.server.ISession;
+import org.eclipse.emf.cdo.server.IStoreAccessor;
+import org.eclipse.emf.cdo.server.IStoreAccessor.DurableLocking2;
+import org.eclipse.emf.cdo.server.IStoreAccessor.QueryXRefsContext;
+import org.eclipse.emf.cdo.server.ITransaction;
+import org.eclipse.emf.cdo.server.IView;
+import org.eclipse.emf.cdo.server.StoreThreadLocal;
+import org.eclipse.emf.cdo.server.mem.IMEMStore;
+import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranch;
+import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranchManager;
+import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranchManager.BranchLoader;
+import org.eclipse.emf.cdo.spi.common.commit.CDOChangeSetSegment;
+import org.eclipse.emf.cdo.spi.common.commit.InternalCDOCommitInfoManager;
+import org.eclipse.emf.cdo.spi.common.revision.DetachedCDORevision;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+import org.eclipse.emf.cdo.spi.common.revision.SyntheticCDORevision;
+import org.eclipse.emf.cdo.spi.server.InternalLockManager;
+import org.eclipse.emf.cdo.spi.server.LongIDStore;
+import org.eclipse.emf.cdo.spi.server.StoreAccessorPool;
+
+import org.eclipse.net4j.util.HexUtil;
+import org.eclipse.net4j.util.ObjectUtil;
+import org.eclipse.net4j.util.ReflectUtil.ExcludeFromDump;
+import org.eclipse.net4j.util.collection.Pair;
+import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
+import org.eclipse.net4j.util.io.IOUtil;
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.CharArrayReader;
+import java.io.CharArrayWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.Writer;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+/**
+ * @author Simon McDuff
+ */
+public class MEMStore extends LongIDStore implements IMEMStore, BranchLoader, DurableLocking2
+{
+  public static final String TYPE = "mem"; //$NON-NLS-1$
+
+  private long creationTime;
+
+  private Map<String, String> properties = new HashMap<String, String>();
+
+  private Map<Integer, BranchInfo> branchInfos = new HashMap<Integer, BranchInfo>();
+
+  private int lastBranchID;
+
+  private int lastLocalBranchID;
+
+  private Map<Object, List<InternalCDORevision>> revisions = new HashMap<Object, List<InternalCDORevision>>();
+
+  private List<CommitInfo> commitInfos = new ArrayList<CommitInfo>();
+
+  private Map<CDOID, EClass> objectTypes = new HashMap<CDOID, EClass>();
+
+  private Map<String, LockArea> lockAreas = new HashMap<String, LockArea>();
+
+  private Map<String, Object> lobs = new HashMap<String, Object>();
+
+  private int listLimit;
+
+  @ExcludeFromDump
+  private transient EStructuralFeature resourceNameFeature;
+
+  /**
+   * @param listLimit
+   *          See {@link #setListLimit(int)}.
+   * @since 2.0
+   */
+  public MEMStore(int listLimit)
+  {
+    super(TYPE, set(ChangeFormat.REVISION, ChangeFormat.DELTA), set(RevisionTemporality.NONE,
+        RevisionTemporality.AUDITING), set(RevisionParallelism.NONE, RevisionParallelism.BRANCHING));
+    setRevisionTemporality(RevisionTemporality.AUDITING);
+    setRevisionParallelism(RevisionParallelism.BRANCHING);
+    this.listLimit = listLimit;
+  }
+
+  public MEMStore()
+  {
+    this(UNLIMITED);
+  }
+
+  @Override
+  public CDOID createObjectID(String val)
+  {
+    if (getRepository().getIDGenerationLocation() == IDGenerationLocation.CLIENT)
+    {
+      byte[] decoded = CDOIDUtil.decodeUUID(val);
+      return CDOIDUtil.createUUID(decoded);
+    }
+
+    return super.createObjectID(val);
+  }
+
+  @Override
+  public boolean isLocal(CDOID id)
+  {
+    if (getRepository().getIDGenerationLocation() == IDGenerationLocation.CLIENT)
+    {
+      return false;
+    }
+
+    return super.isLocal(id);
+  }
+
+  @Override
+  public void ensureLastObjectID(CDOID id)
+  {
+    if (getRepository().getIDGenerationLocation() == IDGenerationLocation.CLIENT)
+    {
+      return;
+    }
+
+    super.ensureLastObjectID(id);
+  }
+
+  public synchronized Map<String, String> getPersistentProperties(Set<String> names)
+  {
+    if (names == null || names.isEmpty())
+    {
+      return new HashMap<String, String>(properties);
+    }
+
+    Map<String, String> result = new HashMap<String, String>();
+    for (String name : names)
+    {
+      String value = properties.get(name);
+      if (value != null)
+      {
+        result.put(name, value);
+      }
+    }
+
+    return result;
+  }
+
+  public synchronized void setPersistentProperties(Map<String, String> properties)
+  {
+    this.properties.putAll(properties);
+  }
+
+  public synchronized void removePersistentProperties(Set<String> names)
+  {
+    for (String name : names)
+    {
+      properties.remove(name);
+    }
+  }
+
+  public synchronized Pair<Integer, Long> createBranch(int branchID, BranchInfo branchInfo)
+  {
+    if (branchID == NEW_BRANCH)
+    {
+      branchID = ++lastBranchID;
+    }
+    else if (branchID == NEW_LOCAL_BRANCH)
+    {
+      branchID = --lastLocalBranchID;
+    }
+
+    branchInfos.put(branchID, branchInfo);
+    return new Pair<Integer, Long>(branchID, branchInfo.getBaseTimeStamp());
+  }
+
+  public synchronized BranchInfo loadBranch(int branchID)
+  {
+    return branchInfos.get(branchID);
+  }
+
+  public synchronized SubBranchInfo[] loadSubBranches(int branchID)
+  {
+    List<SubBranchInfo> result = new ArrayList<SubBranchInfo>();
+    for (Entry<Integer, BranchInfo> entry : branchInfos.entrySet())
+    {
+      BranchInfo branchInfo = entry.getValue();
+      if (branchInfo.getBaseBranchID() == branchID)
+      {
+        int id = entry.getKey();
+        result.add(new SubBranchInfo(id, branchInfo.getName(), branchInfo.getBaseTimeStamp()));
+      }
+    }
+
+    return result.toArray(new SubBranchInfo[result.size()]);
+  }
+
+  public synchronized int loadBranches(int startID, int endID, CDOBranchHandler handler)
+  {
+    int count = 0;
+    InternalCDOBranchManager branchManager = getRepository().getBranchManager();
+    for (Entry<Integer, BranchInfo> entry : branchInfos.entrySet())
+    {
+      int id = entry.getKey();
+      if (startID <= id && (id <= endID || endID == 0))
+      {
+        BranchInfo branchInfo = entry.getValue();
+        InternalCDOBranch branch = branchManager.getBranch(id, branchInfo);
+        handler.handleBranch(branch);
+        ++count;
+      }
+    }
+
+    return count;
+  }
+
+  public synchronized void loadCommitInfos(CDOBranch branch, long startTime, long endTime, CDOCommitInfoHandler handler)
+  {
+    InternalCDOCommitInfoManager manager = getRepository().getCommitInfoManager();
+    for (int i = 0; i < commitInfos.size(); i++)
+    {
+      CommitInfo info = commitInfos.get(i);
+      if (startTime != CDOBranchPoint.UNSPECIFIED_DATE && info.getTimeStamp() < startTime)
+      {
+        continue;
+      }
+
+      if (endTime != CDOBranchPoint.UNSPECIFIED_DATE && info.getTimeStamp() > endTime)
+      {
+        continue;
+      }
+
+      if (branch != null && !ObjectUtil.equals(info.getBranch(), branch))
+      {
+        continue;
+      }
+
+      info.handle(manager, handler);
+    }
+  }
+
+  public synchronized Set<CDOID> readChangeSet(CDOChangeSetSegment[] segments)
+  {
+    Set<CDOID> ids = new HashSet<CDOID>();
+    for (CDOChangeSetSegment segment : segments)
+    {
+      for (List<InternalCDORevision> list : revisions.values())
+      {
+        readChangeSet(segment, list, ids);
+      }
+    }
+
+    return ids;
+  }
+
+  private void readChangeSet(CDOChangeSetSegment segment, List<InternalCDORevision> list, Set<CDOID> ids)
+  {
+    long startTime = segment.getTimeStamp();
+    long endTime = segment.getEndTime();
+    boolean listCheckDone = false;
+    for (InternalCDORevision revision : list)
+    {
+      CDOID id = revision.getID();
+      if (!listCheckDone)
+      {
+        if (ids.contains(id))
+        {
+          return;
+        }
+
+        if (!ObjectUtil.equals(revision.getBranch(), segment.getBranch()))
+        {
+          return;
+        }
+
+        listCheckDone = true;
+      }
+
+      if (CDOCommonUtil.isValidTimeStamp(revision.getTimeStamp(), startTime, endTime))
+      {
+        ids.add(id);
+      }
+    }
+  }
+
+  public synchronized void handleRevisions(EClass eClass, CDOBranch branch, long timeStamp, boolean exactTime,
+      CDORevisionHandler handler)
+  {
+    for (List<InternalCDORevision> list : revisions.values())
+    {
+      for (InternalCDORevision revision : list)
+      {
+        if (!handleRevision(revision, eClass, branch, timeStamp, exactTime, handler))
+        {
+          return;
+        }
+      }
+    }
+  }
+
+  private boolean handleRevision(InternalCDORevision revision, EClass eClass, CDOBranch branch, long timeStamp,
+      boolean exactTime, CDORevisionHandler handler)
+  {
+    if (eClass != null && revision.getEClass() != eClass)
+    {
+      return true;
+    }
+
+    if (branch != null && !ObjectUtil.equals(revision.getBranch(), branch))
+    {
+      return true;
+    }
+
+    if (timeStamp != CDOBranchPoint.INVALID_DATE)
+    {
+      if (exactTime)
+      {
+        if (timeStamp != CDOBranchPoint.UNSPECIFIED_DATE && revision.getTimeStamp() != timeStamp)
+        {
+          return true;
+        }
+      }
+      else
+      {
+        if (!revision.isValid(timeStamp))
+        {
+          return true;
+        }
+      }
+    }
+
+    return handler.handleRevision(revision);
+  }
+
+  /**
+   * @since 2.0
+   */
+  public int getListLimit()
+  {
+    return listLimit;
+  }
+
+  /**
+   * @since 2.0
+   */
+  public synchronized void setListLimit(int listLimit)
+  {
+    if (listLimit != UNLIMITED && this.listLimit != listLimit)
+    {
+      for (List<InternalCDORevision> list : revisions.values())
+      {
+        enforceListLimit(list);
+      }
+    }
+
+    this.listLimit = listLimit;
+  }
+
+  /**
+   * @since 2.0
+   */
+  public synchronized List<InternalCDORevision> getCurrentRevisions()
+  {
+    ArrayList<InternalCDORevision> simpleRevisions = new ArrayList<InternalCDORevision>();
+    Iterator<List<InternalCDORevision>> itr = revisions.values().iterator();
+    while (itr.hasNext())
+    {
+      List<InternalCDORevision> list = itr.next();
+      InternalCDORevision revision = list.get(list.size() - 1);
+      simpleRevisions.add(revision);
+    }
+
+    return simpleRevisions;
+  }
+
+  public synchronized InternalCDORevision getRevisionByVersion(CDOID id, CDOBranchVersion branchVersion)
+  {
+    Object listKey = getListKey(id, branchVersion.getBranch());
+    List<InternalCDORevision> list = revisions.get(listKey);
+    if (list == null)
+    {
+      return null;
+    }
+
+    return getRevisionByVersion(list, branchVersion.getVersion());
+  }
+
+  /**
+   * @since 2.0
+   */
+  public synchronized InternalCDORevision getRevision(CDOID id, CDOBranchPoint branchPoint)
+  {
+    Object listKey = getListKey(id, branchPoint.getBranch());
+    if (branchPoint.getTimeStamp() == CDORevision.UNSPECIFIED_DATE)
+    {
+      List<InternalCDORevision> list = revisions.get(listKey);
+      if (list == null)
+      {
+        return null;
+      }
+
+      return list.get(list.size() - 1);
+    }
+
+    if (!getRepository().isSupportingAudits())
+    {
+      throw new UnsupportedOperationException("Auditing not supported");
+    }
+
+    List<InternalCDORevision> list = revisions.get(listKey);
+    if (list == null)
+    {
+      return null;
+    }
+
+    return getRevision(list, branchPoint);
+  }
+
+  public synchronized void addRevision(InternalCDORevision revision, boolean raw)
+  {
+    Object listKey = getListKey(revision.getID(), revision.getBranch());
+    List<InternalCDORevision> list = revisions.get(listKey);
+    if (list == null)
+    {
+      list = new ArrayList<InternalCDORevision>();
+      revisions.put(listKey, list);
+    }
+
+    addRevision(list, revision, raw);
+
+    if (raw)
+    {
+      ensureLastObjectID(revision.getID());
+    }
+  }
+
+  public synchronized void addCommitInfo(CDOBranch branch, long timeStamp, long previousTimeStamp, String userID,
+      String comment)
+  {
+    int index = commitInfos.size() - 1;
+    while (index >= 0)
+    {
+      CommitInfo info = commitInfos.get(index);
+      if (timeStamp > info.getTimeStamp())
+      {
+        break;
+      }
+
+      --index;
+    }
+
+    CommitInfo commitInfo = new CommitInfo(branch, timeStamp, previousTimeStamp, userID, comment);
+    commitInfos.add(index + 1, commitInfo);
+  }
+
+  /**
+   * @since 2.0
+   */
+  public synchronized boolean rollbackRevision(InternalCDORevision revision)
+  {
+    CDOID id = revision.getID();
+    CDOBranch branch = revision.getBranch();
+    int version = revision.getVersion();
+
+    Object listKey = getListKey(id, branch);
+    List<InternalCDORevision> list = revisions.get(listKey);
+    if (list == null)
+    {
+      return false;
+    }
+
+    for (Iterator<InternalCDORevision> it = list.iterator(); it.hasNext();)
+    {
+      InternalCDORevision rev = it.next();
+      if (rev.getVersion() == version)
+      {
+        it.remove();
+        return true;
+      }
+      else if (rev.getVersion() == version - 1)
+      {
+        rev.setRevised(CDORevision.UNSPECIFIED_DATE);
+      }
+    }
+
+    return false;
+  }
+
+  /**
+   * @since 3.0
+   */
+  public synchronized DetachedCDORevision detachObject(CDOID id, CDOBranch branch, long timeStamp)
+  {
+    Object listKey = getListKey(id, branch);
+    List<InternalCDORevision> list = revisions.get(listKey);
+    if (list != null)
+    {
+      InternalCDORevision revision = getRevision(list, branch.getHead());
+      if (revision != null)
+      {
+        revision.setRevised(timeStamp - 1);
+      }
+    }
+
+    int version;
+    if (list == null)
+    {
+      list = new ArrayList<InternalCDORevision>();
+      revisions.put(listKey, list);
+      version = CDOBranchVersion.FIRST_VERSION;
+    }
+    else
+    {
+      version = getHighestVersion(list) + 1;
+    }
+
+    EClass eClass = getObjectType(id);
+    DetachedCDORevision detached = new DetachedCDORevision(eClass, id, branch, version, timeStamp);
+    addRevision(list, detached, false);
+    return detached;
+  }
+
+  /**
+   * @since 2.0
+   */
+  public synchronized void queryResources(IStoreAccessor.QueryResourcesContext context)
+  {
+    CDOID folderID = context.getFolderID();
+    String name = context.getName();
+    boolean exactMatch = context.exactMatch();
+    for (Entry<Object, List<InternalCDORevision>> entry : revisions.entrySet())
+    {
+      CDOBranch branch = getBranch(entry.getKey());
+      if (!ObjectUtil.equals(branch, context.getBranch()))
+      {
+        continue;
+      }
+
+      List<InternalCDORevision> list = entry.getValue();
+      if (list.isEmpty())
+      {
+        continue;
+      }
+
+      InternalCDORevision revision = list.get(0);
+      if (revision instanceof SyntheticCDORevision)
+      {
+        continue;
+      }
+
+      if (!revision.isResourceNode())
+      {
+        continue;
+      }
+
+      revision = getRevision(list, context);
+      if (revision == null || revision instanceof DetachedCDORevision)
+      {
+        continue;
+      }
+
+      CDOID revisionFolder = (CDOID)revision.data().getContainerID();
+      if (!CDOIDUtil.equals(revisionFolder, folderID))
+      {
+        continue;
+      }
+
+      String revisionName = (String)revision.data().get(resourceNameFeature, 0);
+      boolean useEquals = exactMatch || revisionName == null || name == null;
+      boolean match = useEquals ? ObjectUtil.equals(revisionName, name) : revisionName.startsWith(name);
+
+      if (match)
+      {
+        if (!context.addResource(revision.getID()))
+        {
+          // No more results allowed
+          break;
+        }
+      }
+    }
+  }
+
+  public synchronized void queryXRefs(QueryXRefsContext context)
+  {
+    Set<CDOID> targetIDs = context.getTargetObjects().keySet();
+    Map<EClass, List<EReference>> sourceCandidates = context.getSourceCandidates();
+
+    for (Entry<Object, List<InternalCDORevision>> entry : revisions.entrySet())
+    {
+      CDOBranch branch = getBranch(entry.getKey());
+      if (!ObjectUtil.equals(branch, context.getBranch()))
+      {
+        continue;
+      }
+
+      List<InternalCDORevision> list = entry.getValue();
+      if (list.isEmpty())
+      {
+        continue;
+      }
+
+      InternalCDORevision revision = getRevision(list, context);
+      if (revision == null || revision instanceof SyntheticCDORevision)
+      {
+        continue;
+      }
+
+      EClass eClass = revision.getEClass();
+      CDOID sourceID = revision.getID();
+
+      List<EReference> eReferences = sourceCandidates.get(eClass);
+      if (eReferences != null)
+      {
+        for (EReference eReference : eReferences)
+        {
+          Object value = revision.getValue(eReference);
+          if (value != null)
+          {
+            if (eReference.isMany())
+            {
+              @SuppressWarnings("unchecked")
+              List<CDOID> ids = (List<CDOID>)value;
+              int index = 0;
+              for (CDOID id : ids)
+              {
+                if (!queryXRefs(context, targetIDs, id, sourceID, eReference, index++))
+                {
+                  return;
+                }
+              }
+            }
+            else
+            {
+              CDOID id = (CDOID)value;
+              if (!queryXRefs(context, targetIDs, id, sourceID, eReference, 0))
+              {
+                return;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+
+  private boolean queryXRefs(QueryXRefsContext context, Set<CDOID> targetIDs, CDOID targetID, CDOID sourceID,
+      EReference sourceReference, int index)
+  {
+    for (CDOID id : targetIDs)
+    {
+      if (id.equals(targetID))
+      {
+        if (!context.addXRef(targetID, sourceID, sourceReference, index))
+        {
+          // No more results allowed
+          return false;
+        }
+      }
+    }
+
+    return true;
+  }
+
+  public synchronized void rawExport(CDODataOutput out, int fromBranchID, int toBranchID, long fromCommitTime,
+      long toCommitTime)
+  {
+    // TODO: implement MEMStore.rawExport(out, fromBranchID, toBranchID, fromCommitTime, toCommitTime)
+    throw new UnsupportedOperationException();
+  }
+
+  public synchronized void rawImport(CDODataInput in, int fromBranchID, int toBranchID, long fromCommitTime,
+      long toCommitTime, OMMonitor monitor)
+  {
+    // TODO: implement MEMStore.rawImport(in, fromBranchID, toBranchID, fromCommitTime, toCommitTime, monitor)
+    throw new UnsupportedOperationException();
+  }
+
+  public synchronized void rawDelete(CDOID id, int version, CDOBranch branch)
+  {
+    Object listKey = getListKey(id, branch);
+    List<InternalCDORevision> list = revisions.get(listKey);
+    if (list != null)
+    {
+      for (Iterator<InternalCDORevision> it = list.iterator(); it.hasNext();)
+      {
+        InternalCDORevision rev = it.next();
+        if (rev.getVersion() == version)
+        {
+          it.remove();
+          break;
+        }
+      }
+    }
+  }
+
+  public synchronized LockArea createLockArea(String userID, CDOBranchPoint branchPoint, boolean readOnly,
+      Map<CDOID, LockGrade> locks)
+  {
+    return createLockArea(null, userID, branchPoint, readOnly, locks);
+  }
+
+  public synchronized LockArea createLockArea(String durableLockingID, String userID, CDOBranchPoint branchPoint,
+      boolean readOnly, Map<CDOID, LockGrade> locks)
+  {
+    if (durableLockingID != null)
+    {
+      // If the caller is specifying the ID, make sure there is no area with this ID yet
+      if (lockAreas.containsKey(durableLockingID))
+      {
+        throw new LockAreaAlreadyExistsException(durableLockingID);
+      }
+    }
+    else
+    {
+      do
+      {
+        durableLockingID = CDOLockUtil.createDurableLockingID();
+      } while (lockAreas.containsKey(durableLockingID));
+    }
+
+    LockArea area = CDOLockUtil.createLockArea(durableLockingID, userID, branchPoint, readOnly, locks);
+    lockAreas.put(durableLockingID, area);
+    return area;
+  }
+
+  public synchronized void updateLockArea(LockArea lockArea)
+  {
+    String durableLockingID = lockArea.getDurableLockingID();
+    lockAreas.put(durableLockingID, lockArea);
+  }
+
+  public synchronized LockArea getLockArea(String durableLockingID) throws LockAreaNotFoundException
+  {
+    LockArea area = lockAreas.get(durableLockingID);
+    if (area == null)
+    {
+      throw new LockAreaNotFoundException(durableLockingID);
+    }
+
+    return area;
+  }
+
+  public synchronized void getLockAreas(String userIDPrefix, Handler handler)
+  {
+    for (LockArea area : lockAreas.values())
+    {
+      String userID = area.getUserID();
+      if (userID == null || userID.startsWith(userIDPrefix))
+      {
+        if (!handler.handleLockArea(area))
+        {
+          return;
+        }
+      }
+    }
+  }
+
+  public synchronized void deleteLockArea(String durableLockingID)
+  {
+    lockAreas.remove(durableLockingID);
+  }
+
+  public synchronized void lock(String durableLockingID, LockType type, Collection<? extends Object> objectsToLock)
+  {
+    LockArea area = getLockArea(durableLockingID);
+    Map<CDOID, LockGrade> locks = area.getLocks();
+
+    InternalLockManager lockManager = getRepository().getLockManager();
+    for (Object objectToLock : objectsToLock)
+    {
+      CDOID id = lockManager.getLockKeyID(objectToLock);
+      LockGrade grade = locks.get(id);
+      if (grade != null)
+      {
+        grade = grade.getUpdated(type, true);
+      }
+      else
+      {
+        grade = LockGrade.get(type);
+      }
+
+      locks.put(id, grade);
+    }
+  }
+
+  public synchronized void unlock(String durableLockingID, LockType type, Collection<? extends Object> objectsToUnlock)
+  {
+    LockArea area = getLockArea(durableLockingID);
+    Map<CDOID, LockGrade> locks = area.getLocks();
+
+    InternalLockManager lockManager = getRepository().getLockManager();
+    for (Object objectToUnlock : objectsToUnlock)
+    {
+      CDOID id = lockManager.getLockKeyID(objectToUnlock);
+      LockGrade grade = locks.get(id);
+      if (grade != null)
+      {
+        grade = grade.getUpdated(type, false);
+        if (grade == LockGrade.NONE)
+        {
+          locks.remove(id);
+        }
+      }
+    }
+  }
+
+  public synchronized void unlock(String durableLockingID)
+  {
+    LockArea area = getLockArea(durableLockingID);
+    Map<CDOID, LockGrade> locks = area.getLocks();
+    locks.clear();
+  }
+
+  public synchronized void queryLobs(List<byte[]> ids)
+  {
+    for (Iterator<byte[]> it = ids.iterator(); it.hasNext();)
+    {
+      byte[] id = it.next();
+      String key = HexUtil.bytesToHex(id);
+      if (!lobs.containsKey(key))
+      {
+        it.remove();
+      }
+    }
+  }
+
+  public void handleLobs(long fromTime, long toTime, CDOLobHandler handler) throws IOException
+  {
+    for (Entry<String, Object> entry : lobs.entrySet())
+    {
+      byte[] id = HexUtil.hexToBytes(entry.getKey());
+      Object lob = entry.getValue();
+      if (lob instanceof byte[])
+      {
+        byte[] blob = (byte[])lob;
+        ByteArrayInputStream in = new ByteArrayInputStream(blob);
+        OutputStream out = handler.handleBlob(id, blob.length);
+        if (out != null)
+        {
+          try
+          {
+            IOUtil.copyBinary(in, out, blob.length);
+          }
+          finally
+          {
+            IOUtil.close(out);
+          }
+        }
+      }
+      else
+      {
+        char[] clob = (char[])lob;
+        CharArrayReader in = new CharArrayReader(clob);
+        Writer out = handler.handleClob(id, clob.length);
+        if (out != null)
+        {
+          try
+          {
+            IOUtil.copyCharacter(in, out, clob.length);
+          }
+          finally
+          {
+            IOUtil.close(out);
+          }
+        }
+      }
+    }
+  }
+
+  public synchronized void loadLob(byte[] id, OutputStream out) throws IOException
+  {
+    String key = HexUtil.bytesToHex(id);
+    Object lob = lobs.get(key);
+    if (lob == null)
+    {
+      throw new IOException("Lob not found: " + key);
+    }
+
+    if (lob instanceof byte[])
+    {
+      byte[] blob = (byte[])lob;
+      ByteArrayInputStream in = new ByteArrayInputStream(blob);
+      IOUtil.copyBinary(in, out, blob.length);
+    }
+    else
+    {
+      char[] clob = (char[])lob;
+      CharArrayReader in = new CharArrayReader(clob);
+      IOUtil.copyCharacter(in, new OutputStreamWriter(out), clob.length);
+    }
+  }
+
+  public synchronized void writeBlob(byte[] id, long size, InputStream inputStream) throws IOException
+  {
+    ByteArrayOutputStream out = new ByteArrayOutputStream();
+    IOUtil.copyBinary(inputStream, out, size);
+    lobs.put(HexUtil.bytesToHex(id), out.toByteArray());
+  }
+
+  public synchronized void writeClob(byte[] id, long size, Reader reader) throws IOException
+  {
+    CharArrayWriter out = new CharArrayWriter();
+    IOUtil.copyCharacter(reader, out, size);
+    lobs.put(HexUtil.bytesToHex(id), out.toCharArray());
+  }
+
+  @Override
+  public MEMStoreAccessor createReader(ISession session)
+  {
+    return new MEMStoreAccessor(this, session);
+  }
+
+  /**
+   * @since 2.0
+   */
+  @Override
+  public MEMStoreAccessor createWriter(ITransaction transaction)
+  {
+    return new MEMStoreAccessor(this, transaction);
+  }
+
+  /**
+   * @since 2.0
+   */
+  public long getCreationTime()
+  {
+    return creationTime;
+  }
+
+  public void setCreationTime(long creationTime)
+  {
+    this.creationTime = creationTime;
+  }
+
+  public boolean isFirstStart()
+  {
+    return true;
+  }
+
+  public synchronized Map<CDOBranch, List<CDORevision>> getAllRevisions()
+  {
+    Map<CDOBranch, List<CDORevision>> result = new HashMap<CDOBranch, List<CDORevision>>();
+    InternalCDOBranchManager branchManager = getRepository().getBranchManager();
+    result.put(branchManager.getMainBranch(), new ArrayList<CDORevision>());
+
+    for (Integer branchID : branchInfos.keySet())
+    {
+      InternalCDOBranch branch = branchManager.getBranch(branchID);
+      result.put(branch, new ArrayList<CDORevision>());
+    }
+
+    for (List<InternalCDORevision> list : revisions.values())
+    {
+      for (InternalCDORevision revision : list)
+      {
+        CDOBranch branch = revision.getBranch();
+        List<CDORevision> resultList = result.get(branch);
+        resultList.add(revision);
+      }
+    }
+
+    return result;
+  }
+
+  public synchronized EClass getObjectType(CDOID id)
+  {
+    return objectTypes.get(id);
+  }
+
+  /**
+   * @since 2.0
+   */
+  @Override
+  protected void doActivate() throws Exception
+  {
+    super.doActivate();
+    creationTime = getRepository().getTimeStamp();
+
+    if (getRepository().getIDGenerationLocation() == IDGenerationLocation.CLIENT)
+    {
+      setObjectIDTypes(Collections.singleton(CDOID.ObjectType.UUID));
+    }
+  }
+
+  @Override
+  protected void doDeactivate() throws Exception
+  {
+    revisions.clear();
+    branchInfos.clear();
+    commitInfos.clear();
+    objectTypes.clear();
+    properties.clear();
+    resourceNameFeature = null;
+    lastBranchID = 0;
+    lastLocalBranchID = 0;
+    super.doDeactivate();
+  }
+
+  @Override
+  protected StoreAccessorPool getReaderPool(ISession session, boolean forReleasing)
+  {
+    // Pooling of store accessors not supported
+    return null;
+  }
+
+  @Override
+  protected StoreAccessorPool getWriterPool(IView view, boolean forReleasing)
+  {
+    // Pooling of store accessors not supported
+    return null;
+  }
+
+  private Object getListKey(CDOID id, CDOBranch branch)
+  {
+    if (getRevisionParallelism() == RevisionParallelism.NONE)
+    {
+      return id;
+    }
+
+    return new ListKey(id, branch);
+  }
+
+  private CDOBranch getBranch(Object key)
+  {
+    if (key instanceof ListKey)
+    {
+      return ((ListKey)key).getBranch();
+    }
+
+    return getRepository().getBranchManager().getMainBranch();
+  }
+
+  private int getHighestVersion(List<InternalCDORevision> list)
+  {
+    int version = CDOBranchVersion.UNSPECIFIED_VERSION;
+    for (InternalCDORevision revision : list)
+    {
+      if (revision.getVersion() > version)
+      {
+        version = revision.getVersion();
+      }
+    }
+
+    return version;
+  }
+
+  private InternalCDORevision getRevisionByVersion(List<InternalCDORevision> list, int version)
+  {
+    for (InternalCDORevision revision : list)
+    {
+      if (revision.getVersion() == version)
+      {
+        return revision;
+      }
+    }
+
+    return null;
+  }
+
+  private InternalCDORevision getRevision(List<InternalCDORevision> list, CDOBranchPoint branchPoint)
+  {
+    long timeStamp = branchPoint.getTimeStamp();
+    for (InternalCDORevision revision : list)
+    {
+      if (timeStamp == CDORevision.UNSPECIFIED_DATE)
+      {
+        if (!revision.isHistorical())
+        {
+          return revision;
+        }
+      }
+      else
+      {
+        if (revision.isValid(timeStamp))
+        {
+          return revision;
+        }
+      }
+    }
+
+    return null;
+  }
+
+  private void addRevision(List<InternalCDORevision> list, InternalCDORevision revision, boolean raw)
+  {
+    boolean resource = !(revision instanceof SyntheticCDORevision) && revision.isResource();
+    if (resource && resourceNameFeature == null)
+    {
+      resourceNameFeature = revision.getEClass().getEStructuralFeature(CDOModelConstants.RESOURCE_NODE_NAME_ATTRIBUTE);
+    }
+
+    if (!raw)
+    {
+      // Check version conflict
+      int version = revision.getVersion();
+      InternalCDORevision rev = getRevisionByVersion(list, version);
+      if (rev != null)
+      {
+        rev = getRevisionByVersion(list, version);
+        throw new IllegalStateException("Concurrent modification of " + rev.getEClass().getName() + "@" + rev.getID());
+      }
+
+      // Revise old revision
+      int oldVersion = version - 1;
+      if (oldVersion >= CDORevision.UNSPECIFIED_VERSION)
+      {
+        InternalCDORevision oldRevision = getRevisionByVersion(list, oldVersion);
+        if (oldRevision != null)
+        {
+          if (getRepository().isSupportingAudits())
+          {
+            oldRevision.setRevised(revision.getTimeStamp() - 1);
+          }
+          else
+          {
+            list.remove(oldRevision);
+          }
+        }
+      }
+
+      // Check duplicate resource
+      if (resource)
+      {
+        checkDuplicateResource(revision);
+      }
+    }
+
+    // Adjust the list
+    list.add(revision);
+    if (listLimit != UNLIMITED)
+    {
+      enforceListLimit(list);
+    }
+
+    CDOID id = revision.getID();
+    if (!objectTypes.containsKey(id))
+    {
+      objectTypes.put(id, revision.getEClass());
+    }
+  }
+
+  private void checkDuplicateResource(InternalCDORevision revision)
+  {
+    CDOID revisionFolder = (CDOID)revision.data().getContainerID();
+    String revisionName = (String)revision.data().get(resourceNameFeature, 0);
+
+    IStoreAccessor accessor = StoreThreadLocal.getAccessor();
+
+    CDOID resourceID = accessor.readResourceID(revisionFolder, revisionName, revision);
+    if (!CDOIDUtil.isNull(resourceID))
+    {
+      throw new IllegalStateException("Duplicate resource: name=" + revisionName + ", folderID=" + revisionFolder); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+  }
+
+  private void enforceListLimit(List<InternalCDORevision> list)
+  {
+    while (list.size() > listLimit)
+    {
+      list.remove(0);
+    }
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  private static final class ListKey
+  {
+    private CDOID id;
+
+    private CDOBranch branch;
+
+    public ListKey(CDOID id, CDOBranch branch)
+    {
+      this.id = id;
+      this.branch = branch;
+    }
+
+    public CDOID getID()
+    {
+      return id;
+    }
+
+    public CDOBranch getBranch()
+    {
+      return branch;
+    }
+
+    @Override
+    public int hashCode()
+    {
+      return id.hashCode() ^ branch.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj)
+    {
+      if (obj == this)
+      {
+        return true;
+      }
+
+      if (obj instanceof ListKey)
+      {
+        ListKey that = (ListKey)obj;
+        return ObjectUtil.equals(id, that.getID()) && ObjectUtil.equals(branch, that.getBranch());
+      }
+
+      return false;
+    }
+
+    @Override
+    public String toString()
+    {
+      return MessageFormat.format("{0}:{1}", id, branch.getID());
+    }
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  private static final class CommitInfo
+  {
+    private CDOBranch branch;
+
+    private long timeStamp;
+
+    private long previousTimeStamp;
+
+    private String userID;
+
+    private String comment;
+
+    public CommitInfo(CDOBranch branch, long timeStamp, long previousTimeStamp, String userID, String comment)
+    {
+      this.branch = branch;
+      this.timeStamp = timeStamp;
+      this.previousTimeStamp = previousTimeStamp;
+      this.userID = userID;
+      this.comment = comment;
+    }
+
+    public CDOBranch getBranch()
+    {
+      return branch;
+    }
+
+    public long getTimeStamp()
+    {
+      return timeStamp;
+    }
+
+    public void handle(InternalCDOCommitInfoManager manager, CDOCommitInfoHandler handler)
+    {
+      CDOCommitInfo commitInfo = manager.createCommitInfo(branch, timeStamp, previousTimeStamp, userID, comment, null);
+      handler.handleCommitInfo(commitInfo);
+    }
+
+    @Override
+    public String toString()
+    {
+      return MessageFormat.format("CommitInfo[{0}, {1}, {2}, {3}, {4}]", branch, timeStamp, previousTimeStamp, userID,
+          comment);
+    }
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/mem/MEMStoreAccessor.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/mem/MEMStoreAccessor.java
new file mode 100644
index 0000000..55da263
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/mem/MEMStoreAccessor.java
@@ -0,0 +1,502 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Simon McDuff - initial API and implementation
+ *    Eike Stepper - maintenance
+ *    Simon McDuff - bug 213402
+ */
+package org.eclipse.emf.cdo.internal.server.mem;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchHandler;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.branch.CDOBranchVersion;
+import org.eclipse.emf.cdo.common.commit.CDOCommitInfoHandler;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.lob.CDOLobHandler;
+import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockArea.Handler;
+import org.eclipse.emf.cdo.common.protocol.CDODataInput;
+import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
+import org.eclipse.emf.cdo.common.revision.CDORevisionCacheAdder;
+import org.eclipse.emf.cdo.common.revision.CDORevisionHandler;
+import org.eclipse.emf.cdo.common.util.CDOQueryInfo;
+import org.eclipse.emf.cdo.server.IQueryContext;
+import org.eclipse.emf.cdo.server.IQueryHandler;
+import org.eclipse.emf.cdo.server.ISession;
+import org.eclipse.emf.cdo.server.IStoreAccessor.DurableLocking2;
+import org.eclipse.emf.cdo.server.IStoreAccessor.Raw;
+import org.eclipse.emf.cdo.server.ITransaction;
+import org.eclipse.emf.cdo.spi.common.commit.CDOChangeSetSegment;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionDelta;
+import org.eclipse.emf.cdo.spi.server.InternalCommitContext;
+import org.eclipse.emf.cdo.spi.server.LongIDStoreAccessor;
+
+import org.eclipse.net4j.util.WrappedException;
+import org.eclipse.net4j.util.collection.Pair;
+import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.ConcurrentModificationException;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author Simon McDuff
+ */
+public class MEMStoreAccessor extends LongIDStoreAccessor implements Raw, DurableLocking2
+{
+  private final IQueryHandler testQueryHandler = new IQueryHandler()
+  {
+    public void executeQuery(CDOQueryInfo info, IQueryContext queryContext)
+    {
+      List<Object> filters = new ArrayList<Object>();
+      Object context = info.getParameters().get("context"); //$NON-NLS-1$
+      Long sleep = (Long)info.getParameters().get("sleep"); //$NON-NLS-1$
+      if (context != null)
+      {
+        if (context instanceof EClass)
+        {
+          final EClass eClass = (EClass)context;
+          filters.add(new Object()
+          {
+            @Override
+            public int hashCode()
+            {
+              return eClass.hashCode();
+            }
+
+            @Override
+            public boolean equals(Object obj)
+            {
+              InternalCDORevision revision = (InternalCDORevision)obj;
+              return revision.getEClass().equals(eClass);
+            }
+          });
+        }
+      }
+
+      for (InternalCDORevision revision : getStore().getCurrentRevisions())
+      {
+        if (sleep != null)
+        {
+          try
+          {
+            Thread.sleep(sleep);
+          }
+          catch (InterruptedException ex)
+          {
+            throw WrappedException.wrap(ex);
+          }
+        }
+
+        boolean valid = true;
+
+        for (Object filter : filters)
+        {
+          if (!filter.equals(revision))
+          {
+            valid = false;
+            break;
+          }
+        }
+
+        if (valid)
+        {
+          if (!queryContext.addResult(revision))
+          {
+            // No more results allowed
+            break;
+          }
+        }
+      }
+    }
+  };
+
+  private List<InternalCDORevision> newRevisions = new ArrayList<InternalCDORevision>();
+
+  public MEMStoreAccessor(MEMStore store, ISession session)
+  {
+    super(store, session);
+  }
+
+  /**
+   * @since 2.0
+   */
+  public MEMStoreAccessor(MEMStore store, ITransaction transaction)
+  {
+    super(store, transaction);
+  }
+
+  @Override
+  public MEMStore getStore()
+  {
+    return (MEMStore)super.getStore();
+  }
+
+  /**
+   * @since 2.0
+   */
+  public MEMStoreChunkReader createChunkReader(InternalCDORevision revision, EStructuralFeature feature)
+  {
+    return new MEMStoreChunkReader(this, revision, feature);
+  }
+
+  public Collection<InternalCDOPackageUnit> readPackageUnits()
+  {
+    return Collections.emptySet();
+  }
+
+  public EPackage[] loadPackageUnit(InternalCDOPackageUnit packageUnit)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public Pair<Integer, Long> createBranch(int branchID, BranchInfo branchInfo)
+  {
+    return getStore().createBranch(branchID, branchInfo);
+  }
+
+  public BranchInfo loadBranch(int branchID)
+  {
+    return getStore().loadBranch(branchID);
+  }
+
+  public SubBranchInfo[] loadSubBranches(int branchID)
+  {
+    return getStore().loadSubBranches(branchID);
+  }
+
+  public int loadBranches(int startID, int endID, CDOBranchHandler branchHandler)
+  {
+    return getStore().loadBranches(startID, endID, branchHandler);
+  }
+
+  public void loadCommitInfos(CDOBranch branch, long startTime, long endTime, CDOCommitInfoHandler handler)
+  {
+    getStore().loadCommitInfos(branch, startTime, endTime, handler);
+  }
+
+  public Set<CDOID> readChangeSet(OMMonitor monitor, CDOChangeSetSegment... segments)
+  {
+    return getStore().readChangeSet(segments);
+  }
+
+  public InternalCDORevision readRevision(CDOID id, CDOBranchPoint branchPoint, int listChunk,
+      CDORevisionCacheAdder cache)
+  {
+    return getStore().getRevision(id, branchPoint);
+  }
+
+  public InternalCDORevision readRevisionByVersion(CDOID id, CDOBranchVersion branchVersion, int listChunk,
+      CDORevisionCacheAdder cache)
+  {
+    return getStore().getRevisionByVersion(id, branchVersion);
+  }
+
+  public void handleRevisions(EClass eClass, CDOBranch branch, long timeStamp, boolean exactTime,
+      CDORevisionHandler handler)
+  {
+    getStore().handleRevisions(eClass, branch, timeStamp, exactTime, handler);
+  }
+
+  /**
+   * @since 2.0
+   */
+  @Override
+  protected void doCommit(OMMonitor monitor)
+  {
+    // Do nothing
+  }
+
+  @Override
+  public void doWrite(InternalCommitContext context, OMMonitor monitor)
+  {
+    MEMStore store = getStore();
+    synchronized (store)
+    {
+      super.doWrite(context, monitor);
+    }
+  }
+
+  @Override
+  protected void writeCommitInfo(CDOBranch branch, long timeStamp, long previousTimeStamp, String userID,
+      String comment, OMMonitor monitor)
+  {
+    getStore().addCommitInfo(branch, timeStamp, previousTimeStamp, userID, comment);
+  }
+
+  @Override
+  protected void doRollback(CommitContext context)
+  {
+    MEMStore store = getStore();
+    synchronized (store)
+    {
+      for (InternalCDORevision revision : newRevisions)
+      {
+        store.rollbackRevision(revision);
+      }
+    }
+  }
+
+  public void writePackageUnits(InternalCDOPackageUnit[] packageUnits, OMMonitor monitor)
+  {
+    // Do nothing
+  }
+
+  @Override
+  protected void writeRevisions(InternalCDORevision[] revisions, CDOBranch branch, OMMonitor monitor)
+  {
+    for (InternalCDORevision revision : revisions)
+    {
+      writeRevision(revision);
+    }
+  }
+
+  protected void writeRevision(InternalCDORevision revision)
+  {
+    newRevisions.add(revision);
+    getStore().addRevision(revision, false);
+  }
+
+  /**
+   * @since 2.0
+   */
+  @Override
+  protected void writeRevisionDeltas(InternalCDORevisionDelta[] revisionDeltas, CDOBranch branch, long created,
+      OMMonitor monitor)
+  {
+    for (InternalCDORevisionDelta revisionDelta : revisionDeltas)
+    {
+      writeRevisionDelta(revisionDelta, branch, created);
+    }
+  }
+
+  /**
+   * @since 2.0
+   */
+  protected void writeRevisionDelta(InternalCDORevisionDelta revisionDelta, CDOBranch branch, long created)
+  {
+    CDOID id = revisionDelta.getID();
+    CDOBranchVersion version = revisionDelta.getBranch().getVersion(revisionDelta.getVersion());
+    InternalCDORevision revision = getStore().getRevisionByVersion(id, version);
+    if (revision.getVersion() != revisionDelta.getVersion())
+    {
+      throw new ConcurrentModificationException("Trying to update object " + id //$NON-NLS-1$
+          + " that was already modified"); //$NON-NLS-1$
+    }
+
+    InternalCDORevision newRevision = revision.copy();
+    newRevision.adjustForCommit(branch, created);
+
+    revisionDelta.apply(newRevision);
+    writeRevision(newRevision);
+  }
+
+  @Override
+  protected void detachObjects(CDOID[] detachedObjects, CDOBranch branch, long timeStamp, OMMonitor monitor)
+  {
+    for (CDOID id : detachedObjects)
+    {
+      detachObject(id, branch, timeStamp);
+    }
+  }
+
+  /**
+   * @since 3.0
+   */
+  protected void detachObject(CDOID id, CDOBranch branch, long timeStamp)
+  {
+    getStore().detachObject(id, branch, timeStamp);
+  }
+
+  /**
+   * @since 2.0
+   */
+  public void queryResources(QueryResourcesContext context)
+  {
+    getStore().queryResources(context);
+  }
+
+  public void queryXRefs(QueryXRefsContext context)
+  {
+    getStore().queryXRefs(context);
+  }
+
+  public IQueryHandler getQueryHandler(CDOQueryInfo info)
+  {
+    if ("TEST".equals(info.getQueryLanguage())) //$NON-NLS-1$
+    {
+      return testQueryHandler;
+    }
+
+    return null;
+  }
+
+  public void rawExport(CDODataOutput out, int fromBranchID, int toBranchID, long fromCommitTime, long toCommitTime)
+      throws IOException
+  {
+    getStore().rawExport(out, fromBranchID, toBranchID, fromCommitTime, toCommitTime);
+  }
+
+  public void rawImport(CDODataInput in, int fromBranchID, int toBranchID, long fromCommitTime, long toCommitTime,
+      OMMonitor monitor) throws IOException
+  {
+    getStore().rawImport(in, fromBranchID, toBranchID, fromCommitTime, toCommitTime, monitor);
+  }
+
+  public void rawStore(InternalCDOPackageUnit[] packageUnits, OMMonitor monitor)
+  {
+    writePackageUnits(packageUnits, monitor);
+  }
+
+  public void rawStore(InternalCDORevision revision, OMMonitor monitor)
+  {
+    getStore().addRevision(revision, true);
+  }
+
+  public void rawStore(byte[] id, long size, InputStream inputStream) throws IOException
+  {
+    writeBlob(id, size, inputStream);
+  }
+
+  public void rawStore(byte[] id, long size, Reader reader) throws IOException
+  {
+    writeClob(id, size, reader);
+  }
+
+  public void rawStore(CDOBranch branch, long timeStamp, long previousTimeStamp, String userID, String comment,
+      OMMonitor monitor)
+  {
+    writeCommitInfo(branch, timeStamp, previousTimeStamp, userID, comment, monitor);
+  }
+
+  @Deprecated
+  public void rawDelete(CDOID id, int version, CDOBranch branch, EClass eClass, OMMonitor monitor)
+  {
+    throw new UnsupportedOperationException();
+
+    // getStore().rawDelete(id, version, branch);
+  }
+
+  public void rawCommit(double commitWork, OMMonitor monitor)
+  {
+    // Do nothing
+  }
+
+  public LockArea createLockArea(String userID, CDOBranchPoint branchPoint, boolean readOnly,
+      Map<CDOID, LockGrade> locks)
+  {
+    return getStore().createLockArea(userID, branchPoint, readOnly, locks);
+  }
+
+  public LockArea createLockArea(String durableLockingID, String userID, CDOBranchPoint branchPoint, boolean readOnly,
+      Map<CDOID, LockGrade> locks)
+  {
+    return getStore().createLockArea(durableLockingID, userID, branchPoint, readOnly, locks);
+  }
+
+  public void updateLockArea(LockArea lockArea)
+  {
+    getStore().updateLockArea(lockArea);
+  }
+
+  public LockArea getLockArea(String durableLockingID) throws LockAreaNotFoundException
+  {
+    return getStore().getLockArea(durableLockingID);
+  }
+
+  public void getLockAreas(String userIDPrefix, Handler handler)
+  {
+    getStore().getLockAreas(userIDPrefix, handler);
+  }
+
+  public void deleteLockArea(String durableLockingID)
+  {
+    getStore().deleteLockArea(durableLockingID);
+  }
+
+  public void lock(String durableLockingID, LockType type, Collection<? extends Object> objectsToLock)
+  {
+    getStore().lock(durableLockingID, type, objectsToLock);
+  }
+
+  public void unlock(String durableLockingID, LockType type, Collection<? extends Object> objectsToUnlock)
+  {
+    getStore().unlock(durableLockingID, type, objectsToUnlock);
+  }
+
+  public void unlock(String durableLockingID)
+  {
+    getStore().unlock(durableLockingID);
+  }
+
+  public void queryLobs(List<byte[]> ids)
+  {
+    getStore().queryLobs(ids);
+  }
+
+  public void handleLobs(long fromTime, long toTime, CDOLobHandler handler) throws IOException
+  {
+    getStore().handleLobs(fromTime, toTime, handler);
+  }
+
+  public void loadLob(byte[] id, OutputStream out) throws IOException
+  {
+    getStore().loadLob(id, out);
+  }
+
+  @Override
+  protected void writeBlob(byte[] id, long size, InputStream inputStream) throws IOException
+  {
+    getStore().writeBlob(id, size, inputStream);
+  }
+
+  @Override
+  protected void writeClob(byte[] id, long size, Reader reader) throws IOException
+  {
+    getStore().writeClob(id, size, reader);
+  }
+
+  @Override
+  protected void doActivate() throws Exception
+  {
+    // Do nothing
+  }
+
+  @Override
+  protected void doDeactivate() throws Exception
+  {
+    newRevisions.clear();
+  }
+
+  @Override
+  protected void doPassivate() throws Exception
+  {
+    // Pooling of store accessors not supported
+  }
+
+  @Override
+  protected void doUnpassivate() throws Exception
+  {
+    // Pooling of store accessors not supported
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/mem/MEMStoreChunkReader.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/mem/MEMStoreChunkReader.java
new file mode 100644
index 0000000..82e6c63
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/mem/MEMStoreChunkReader.java
@@ -0,0 +1,67 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Simon McDuff - initial API and implementation
+ *    Eike Stepper - maintenance
+ */
+package org.eclipse.emf.cdo.internal.server.mem;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranchVersion;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.server.IStoreAccessor;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+import org.eclipse.emf.cdo.spi.server.StoreChunkReader;
+
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+import java.util.List;
+
+/**
+ * @author Simon McDuff
+ */
+public class MEMStoreChunkReader extends StoreChunkReader
+{
+  /**
+   * @since 2.0
+   */
+  public MEMStoreChunkReader(IStoreAccessor accessor, CDORevision revision, EStructuralFeature feature)
+  {
+    super(accessor, revision, feature);
+  }
+
+  public List<Chunk> executeRead()
+  {
+    CDOID id = getRevision().getID();
+    CDOBranchVersion branchVersion = getRevision();
+
+    MEMStore store = getAccessor().getStore();
+    List<Chunk> chunks = getChunks();
+    for (Chunk chunk : chunks)
+    {
+      int startIndex = chunk.getStartIndex();
+      InternalCDORevision revision = store.getRevisionByVersion(id, branchVersion);
+      for (int i = 0; i < chunk.size(); i++)
+      {
+        Object object = revision.get(getFeature(), startIndex + i);
+        chunk.add(i, object);
+      }
+    }
+
+    return chunks;
+  }
+
+  /**
+   * @since 2.0
+   */
+  @Override
+  public MEMStoreAccessor getAccessor()
+  {
+    return (MEMStoreAccessor)super.getAccessor();
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/mem/MEMStoreFactory.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/mem/MEMStoreFactory.java
new file mode 100644
index 0000000..dd48174
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/mem/MEMStoreFactory.java
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *    Simon McDuff - initial API and implementation
+ *    Eike Stepper - maintenance
+ */
+package org.eclipse.emf.cdo.internal.server.mem;
+
+import org.eclipse.emf.cdo.server.IStore;
+import org.eclipse.emf.cdo.server.IStoreFactory;
+
+import org.w3c.dom.Element;
+
+import java.util.Map;
+
+/**
+ * @author Simon McDuff
+ */
+public class MEMStoreFactory implements IStoreFactory
+{
+  public MEMStoreFactory()
+  {
+  }
+
+  public String getStoreType()
+  {
+    return MEMStore.TYPE;
+  }
+
+  public IStore createStore(String repositoryName, Map<String, String> repositoryProperties, Element storeConfig)
+  {
+    return new MEMStore();
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/messages/Messages.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/messages/Messages.java
new file mode 100644
index 0000000..294f584
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/messages/Messages.java
@@ -0,0 +1,41 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *    Victor Roldan Betancort - initial API and implementation
+ *    Eike Stepper - maintenance
+ */
+package org.eclipse.emf.cdo.internal.server.messages;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+/**
+ * @author Victor Roldan Betancort
+ */
+public class Messages
+{
+  private static final String BUNDLE_NAME = "org.eclipse.emf.cdo.internal.server.messages.messages"; //$NON-NLS-1$
+
+  private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle(BUNDLE_NAME);
+
+  private Messages()
+  {
+  }
+
+  public static String getString(String key)
+  {
+    try
+    {
+      return RESOURCE_BUNDLE.getString(key);
+    }
+    catch (MissingResourceException e)
+    {
+      return '!' + key + '!';
+    }
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/messages/messages.properties b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/messages/messages.properties
new file mode 100644
index 0000000..7dc1b9e
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/messages/messages.properties
@@ -0,0 +1,16 @@
+# Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#    Victor Roldan Betancort - initial API and implementation
+#    Eike Stepper - maintenance
+
+CDOServerApplication.1=CDO server starting
+CDOServerApplication.6=CDO server started
+CDOServerApplication.7=CDO server stopping
+CDOServerApplication.8=CDO server stopped
+CDOServerApplication.5=CDO server configuration not found:
+CDOServerApplication.3=No CDO repositories configured:
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/syncing/FailoverParticipant.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/syncing/FailoverParticipant.java
new file mode 100644
index 0000000..dcfab82
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/syncing/FailoverParticipant.java
@@ -0,0 +1,131 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.internal.server.syncing;
+
+import org.eclipse.emf.cdo.spi.server.InternalCommitContext;
+import org.eclipse.emf.cdo.spi.server.InternalFailoverParticipant;
+import org.eclipse.emf.cdo.spi.server.InternalTransaction;
+
+/**
+ * @author Eike Stepper
+ */
+public class FailoverParticipant extends SynchronizableRepository implements InternalFailoverParticipant
+{
+  private boolean allowBackupCommits;
+
+  public FailoverParticipant()
+  {
+    setState(OFFLINE);
+  }
+
+  public boolean isAllowBackupCommits()
+  {
+    return allowBackupCommits;
+  }
+
+  public void setAllowBackupCommits(boolean allowBackupCommits)
+  {
+    this.allowBackupCommits = allowBackupCommits;
+  }
+
+  @Override
+  public void setType(Type type)
+  {
+    checkArg(type == MASTER || type == BACKUP, "Type must be MASTER or BACKUP");
+    super.setType(type);
+  }
+
+  @Override
+  protected void changingType(Type oldType, Type newType)
+  {
+    if (isActive())
+    {
+      if (newType == MASTER)
+      {
+        // Switch off synchronizer
+        doStopSynchronization();
+      }
+      else
+      {
+        // Bug 312879
+        setReplicationCountersToLatest();
+
+        // Switch on synchronizer
+        doStartSynchronization();
+      }
+    }
+
+    super.changingType(oldType, newType);
+  }
+
+  @Override
+  protected void initRootResource()
+  {
+    if (getType() == BACKUP)
+    {
+      super.initRootResource();
+    }
+    else
+    {
+      doInitRootResource();
+    }
+  }
+
+  protected void doStartSynchronization()
+  {
+    super.startSynchronization();
+  }
+
+  protected void doStopSynchronization()
+  {
+    super.stopSynchronization();
+  }
+
+  @Override
+  protected void startSynchronization()
+  {
+    if (getType() == BACKUP)
+    {
+      doStartSynchronization();
+    }
+  }
+
+  @Override
+  protected void stopSynchronization()
+  {
+    if (getType() == BACKUP)
+    {
+      doStopSynchronization();
+    }
+  }
+
+  @Override
+  public InternalCommitContext createCommitContext(InternalTransaction transaction)
+  {
+    if (getType() == BACKUP)
+    {
+      if (getState() != ONLINE)
+      {
+        throw new IllegalStateException("Backup repository is not online");
+      }
+
+      if (allowBackupCommits || transaction.getSession() == getReplicatorSession())
+      {
+        return createWriteThroughCommitContext(transaction);
+      }
+
+      throw new IllegalStateException(
+          "Only the repository synchronizer is allowed to commit transactions to a backup repository");
+    }
+
+    return createNormalCommitContext(transaction);
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/syncing/OfflineClone.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/syncing/OfflineClone.java
new file mode 100644
index 0000000..d551fc5
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/syncing/OfflineClone.java
@@ -0,0 +1,249 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.internal.server.syncing;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchVersion;
+import org.eclipse.emf.cdo.common.commit.CDOChangeKind;
+import org.eclipse.emf.cdo.common.commit.CDOChangeSetData;
+import org.eclipse.emf.cdo.common.commit.CDOCommitData;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.id.CDOIDUtil;
+import org.eclipse.emf.cdo.common.model.CDOPackageUnit;
+import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion;
+import org.eclipse.emf.cdo.common.revision.CDORevisionKey;
+import org.eclipse.emf.cdo.internal.server.TransactionCommitContext;
+import org.eclipse.emf.cdo.server.StoreThreadLocal;
+import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranch;
+import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranchManager;
+import org.eclipse.emf.cdo.spi.common.commit.CDOChangeKindCache;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionDelta;
+import org.eclipse.emf.cdo.spi.server.InternalCommitContext;
+import org.eclipse.emf.cdo.spi.server.InternalTransaction;
+
+import org.eclipse.net4j.util.collection.IndexedList;
+import org.eclipse.net4j.util.om.monitor.Monitor;
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Eike Stepper
+ */
+public class OfflineClone extends SynchronizableRepository
+{
+  public OfflineClone()
+  {
+    setState(OFFLINE);
+  }
+
+  @Override
+  public final Type getType()
+  {
+    return CLONE;
+  }
+
+  @Override
+  public final void setType(Type type)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public InternalCommitContext createCommitContext(InternalTransaction transaction)
+  {
+    CDOBranch branch = transaction.getBranch();
+    if (branch.isLocal())
+    {
+      return createNormalCommitContext(transaction);
+    }
+
+    if (getState() != ONLINE)
+    {
+      return createBranchingCommitContext(transaction, branch);
+    }
+
+    return createWriteThroughCommitContext(transaction);
+  }
+
+  protected InternalCommitContext createBranchingCommitContext(InternalTransaction transaction, CDOBranch branch)
+  {
+    long[] times = createCommitTimeStamp(new Monitor());
+    CDOBranch offlineBranch = createOfflineBranch(branch, times[0] - 1L);
+    transaction.setBranchPoint(offlineBranch.getHead());
+    return new BranchingCommitContext(transaction, times);
+  }
+
+  protected CDOBranch createOfflineBranch(CDOBranch baseBranch, long baseTimeStamp)
+  {
+    try
+    {
+      StoreThreadLocal.setSession(getReplicatorSession());
+      InternalCDOBranchManager branchManager = getBranchManager();
+      return branchManager.createBranch(NEW_LOCAL_BRANCH,
+          "Offline-" + baseTimeStamp, (InternalCDOBranch)baseBranch, baseTimeStamp); //$NON-NLS-1$
+    }
+    finally
+    {
+      StoreThreadLocal.release();
+    }
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  protected static final class CommitContextData implements CDOCommitData
+  {
+    private InternalCommitContext commitContext;
+
+    private CDOChangeKindCache changeKindCache;
+
+    public CommitContextData(InternalCommitContext commitContext)
+    {
+      this.commitContext = commitContext;
+    }
+
+    public boolean isEmpty()
+    {
+      return false;
+    }
+
+    public CDOChangeSetData copy()
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public void merge(CDOChangeSetData changeSetData)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    public List<CDOPackageUnit> getNewPackageUnits()
+    {
+      final InternalCDOPackageUnit[] newPackageUnits = commitContext.getNewPackageUnits();
+      return new IndexedList<CDOPackageUnit>()
+      {
+        @Override
+        public CDOPackageUnit get(int index)
+        {
+          return newPackageUnits[index];
+        }
+
+        @Override
+        public int size()
+        {
+          return newPackageUnits.length;
+        }
+      };
+    }
+
+    public List<CDOIDAndVersion> getNewObjects()
+    {
+      final InternalCDORevision[] newObjects = commitContext.getNewObjects();
+      return new IndexedList<CDOIDAndVersion>()
+      {
+        @Override
+        public CDOIDAndVersion get(int index)
+        {
+          return newObjects[index];
+        }
+
+        @Override
+        public int size()
+        {
+          return newObjects.length;
+        }
+      };
+    }
+
+    public List<CDORevisionKey> getChangedObjects()
+    {
+      final InternalCDORevisionDelta[] changedObjects = commitContext.getDirtyObjectDeltas();
+      return new IndexedList<CDORevisionKey>()
+      {
+        @Override
+        public CDORevisionKey get(int index)
+        {
+          return changedObjects[index];
+        }
+
+        @Override
+        public int size()
+        {
+          return changedObjects.length;
+        }
+      };
+    }
+
+    public List<CDOIDAndVersion> getDetachedObjects()
+    {
+      final CDOID[] detachedObjects = commitContext.getDetachedObjects();
+      return new IndexedList<CDOIDAndVersion>()
+      {
+        @Override
+        public CDOIDAndVersion get(int index)
+        {
+          return CDOIDUtil.createIDAndVersion(detachedObjects[index], CDOBranchVersion.UNSPECIFIED_VERSION);
+        }
+
+        @Override
+        public int size()
+        {
+          return detachedObjects.length;
+        }
+      };
+    }
+
+    public synchronized Map<CDOID, CDOChangeKind> getChangeKinds()
+    {
+      if (changeKindCache == null)
+      {
+        changeKindCache = new CDOChangeKindCache(this);
+      }
+
+      return changeKindCache;
+    }
+
+    public CDOChangeKind getChangeKind(CDOID id)
+    {
+      return getChangeKinds().get(id);
+    }
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  protected final class BranchingCommitContext extends TransactionCommitContext
+  {
+    private long[] times;
+
+    public BranchingCommitContext(InternalTransaction transaction, long[] times)
+    {
+      super(transaction);
+      this.times = times;
+    }
+
+    @Override
+    protected void lockObjects() throws InterruptedException
+    {
+      // Do nothing
+    }
+
+    @Override
+    protected long[] createTimeStamp(OMMonitor monitor)
+    {
+      return times;
+    }
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/syncing/ReplicatorCommitContext.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/syncing/ReplicatorCommitContext.java
new file mode 100644
index 0000000..e69b5a6
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/syncing/ReplicatorCommitContext.java
@@ -0,0 +1,162 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.internal.server.syncing;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.model.CDOPackageUnit;
+import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion;
+import org.eclipse.emf.cdo.common.revision.CDORevisionKey;
+import org.eclipse.emf.cdo.internal.server.TransactionCommitContext;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionDelta;
+import org.eclipse.emf.cdo.spi.server.InternalRepository;
+import org.eclipse.emf.cdo.spi.server.InternalTransaction;
+
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+
+import java.util.List;
+
+/**
+ * TODO Optimize createCommitInfo()
+ * 
+ * @author Eike Stepper
+ */
+public final class ReplicatorCommitContext extends TransactionCommitContext
+{
+  private final CDOCommitInfo commitInfo;
+
+  public ReplicatorCommitContext(InternalTransaction transaction, CDOCommitInfo commitInfo)
+  {
+    super(transaction);
+    this.commitInfo = commitInfo;
+
+    setCommitComment(commitInfo.getComment());
+
+    InternalCDOPackageUnit[] newPackageUnits = getNewPackageUnits(commitInfo, getPackageRegistry());
+    setNewPackageUnits(newPackageUnits);
+
+    InternalCDORevision[] newObjects = getNewObjects(commitInfo);
+    setNewObjects(newObjects);
+
+    InternalCDORevisionDelta[] dirtyObjectDeltas = getDirtyObjectDeltas(commitInfo);
+    setDirtyObjectDeltas(dirtyObjectDeltas);
+
+    CDOID[] detachedObjects = getDetachedObjects(commitInfo);
+    setDetachedObjects(detachedObjects);
+  }
+
+  @Override
+  public String getUserID()
+  {
+    return commitInfo.getUserID();
+  }
+
+  @Override
+  protected long[] createTimeStamp(OMMonitor monitor)
+  {
+    InternalRepository repository = getTransaction().getSession().getManager().getRepository();
+
+    long commitTimeStamp = commitInfo.getTimeStamp();
+    if (commitTimeStamp == CDOBranchPoint.UNSPECIFIED_DATE)
+    {
+      commitTimeStamp = repository.getTimeStamp();
+    }
+
+    return repository.forceCommitTimeStamp(commitInfo.getTimeStamp(), monitor);
+  }
+
+  @Override
+  protected void adjustForCommit()
+  {
+    // Do nothing
+  }
+
+  @Override
+  public void applyIDMappings(OMMonitor monitor)
+  {
+    monitor.done();
+  }
+
+  @Override
+  protected void lockObjects() throws InterruptedException
+  {
+    // Do nothing
+  }
+
+  @Override
+  protected void checkXRefs()
+  {
+    // Do nothing
+  }
+
+  private static InternalCDOPackageUnit[] getNewPackageUnits(CDOCommitInfo commitInfo,
+      InternalCDOPackageRegistry packageRegistry)
+  {
+    List<CDOPackageUnit> list = commitInfo.getNewPackageUnits();
+    InternalCDOPackageUnit[] result = new InternalCDOPackageUnit[list.size()];
+
+    int i = 0;
+    for (CDOPackageUnit packageUnit : list)
+    {
+      result[i] = (InternalCDOPackageUnit)packageUnit;
+      packageRegistry.putPackageUnit(result[i]);
+      ++i;
+    }
+
+    return result;
+  }
+
+  private static InternalCDORevision[] getNewObjects(CDOCommitInfo commitInfo)
+  {
+    List<CDOIDAndVersion> list = commitInfo.getNewObjects();
+    InternalCDORevision[] result = new InternalCDORevision[list.size()];
+
+    int i = 0;
+    for (CDOIDAndVersion revision : list)
+    {
+      result[i++] = (InternalCDORevision)revision;
+    }
+
+    return result;
+  }
+
+  private static InternalCDORevisionDelta[] getDirtyObjectDeltas(CDOCommitInfo commitInfo)
+  {
+    List<CDORevisionKey> list = commitInfo.getChangedObjects();
+    InternalCDORevisionDelta[] result = new InternalCDORevisionDelta[list.size()];
+
+    int i = 0;
+    for (CDORevisionKey delta : list)
+    {
+      result[i++] = (InternalCDORevisionDelta)delta;
+    }
+
+    return result;
+  }
+
+  private static CDOID[] getDetachedObjects(CDOCommitInfo commitInfo)
+  {
+    List<CDOIDAndVersion> list = commitInfo.getDetachedObjects();
+    CDOID[] result = new CDOID[list.size()];
+
+    int i = 0;
+    for (CDOIDAndVersion key : list)
+    {
+      result[i++] = key.getID();
+    }
+
+    return result;
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/syncing/RepositorySynchronizer.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/syncing/RepositorySynchronizer.java
new file mode 100644
index 0000000..dfb44b8
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/syncing/RepositorySynchronizer.java
@@ -0,0 +1,650 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.internal.server.syncing;
+
+import org.eclipse.emf.cdo.common.CDOCommonRepository;
+import org.eclipse.emf.cdo.common.CDOCommonSession.Options.LockNotificationMode;
+import org.eclipse.emf.cdo.common.CDOCommonSession.Options.PassiveUpdateMode;
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchCreatedEvent;
+import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
+import org.eclipse.emf.cdo.internal.common.revision.NOOPRevisionCache;
+import org.eclipse.emf.cdo.internal.server.bundle.OM;
+import org.eclipse.emf.cdo.server.StoreThreadLocal;
+import org.eclipse.emf.cdo.session.CDOSessionConfiguration;
+import org.eclipse.emf.cdo.session.CDOSessionConfigurationFactory;
+import org.eclipse.emf.cdo.session.CDOSessionInvalidationEvent;
+import org.eclipse.emf.cdo.session.CDOSessionLocksChangedEvent;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionCache;
+import org.eclipse.emf.cdo.spi.server.InternalRepositorySynchronizer;
+import org.eclipse.emf.cdo.spi.server.InternalSynchronizableRepository;
+
+import org.eclipse.net4j.util.concurrent.ConcurrencyUtil;
+import org.eclipse.net4j.util.concurrent.QueueRunner;
+import org.eclipse.net4j.util.event.IEvent;
+import org.eclipse.net4j.util.event.IListener;
+import org.eclipse.net4j.util.lifecycle.ILifecycleEvent;
+import org.eclipse.net4j.util.om.monitor.NotifyingMonitor;
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+import org.eclipse.net4j.util.om.trace.ContextTracer;
+
+import org.eclipse.emf.spi.cdo.CDOSessionProtocol;
+import org.eclipse.emf.spi.cdo.InternalCDOSession;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.PriorityBlockingQueue;
+
+/**
+ * @author Eike Stepper
+ * @since 3.0
+ */
+public class RepositorySynchronizer extends QueueRunner implements InternalRepositorySynchronizer
+{
+  public static final int DEFAULT_RETRY_INTERVAL = 3;
+
+  public static final int DEFAULT_MAX_RECOMMITS = 10;
+
+  public static final int DEFAULT_RECOMMIT_INTERVAL = 1;
+
+  private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_REPOSITORY, RepositorySynchronizer.class);
+
+  private static final Integer CONNECT_PRIORITY = 0;
+
+  private static final Integer REPLICATE_PRIORITY = 1;
+
+  private static final Integer BRANCH_PRIORITY = 2;
+
+  private static final Integer COMMIT_PRIORITY = 3;
+
+  private static final Integer LOCKS_PRIORITY = COMMIT_PRIORITY;
+
+  private int retryInterval = DEFAULT_RETRY_INTERVAL;
+
+  private Object connectLock = new Object();
+
+  private InternalSynchronizableRepository localRepository;
+
+  /**
+   * The session that connects to the master; used passively to receive notifications, and actively to request
+   * replications.
+   */
+  private InternalCDOSession remoteSession;
+
+  private RemoteSessionListener remoteSessionListener = new RemoteSessionListener();
+
+  private CDOSessionConfigurationFactory remoteSessionConfigurationFactory;
+
+  private boolean rawReplication;
+
+  private int maxRecommits = DEFAULT_MAX_RECOMMITS;
+
+  private int recommitInterval = DEFAULT_RECOMMIT_INTERVAL;
+
+  private Timer recommitTimer;
+
+  public RepositorySynchronizer()
+  {
+    setDaemon(true);
+  }
+
+  public int getRetryInterval()
+  {
+    return retryInterval;
+  }
+
+  public void setRetryInterval(int retryInterval)
+  {
+    this.retryInterval = retryInterval;
+  }
+
+  public InternalSynchronizableRepository getLocalRepository()
+  {
+    return localRepository;
+  }
+
+  public void setLocalRepository(InternalSynchronizableRepository localRepository)
+  {
+    checkInactive();
+    this.localRepository = localRepository;
+  }
+
+  public CDOSessionConfigurationFactory getRemoteSessionConfigurationFactory()
+  {
+    return remoteSessionConfigurationFactory;
+  }
+
+  public void setRemoteSessionConfigurationFactory(CDOSessionConfigurationFactory masterSessionConfigurationFactory)
+  {
+    checkArg(masterSessionConfigurationFactory, "remoteSessionConfigurationFactory"); //$NON-NLS-1$
+    remoteSessionConfigurationFactory = masterSessionConfigurationFactory;
+  }
+
+  public InternalCDOSession getRemoteSession()
+  {
+    return remoteSession;
+  }
+
+  public boolean isRawReplication()
+  {
+    return rawReplication;
+  }
+
+  public void setRawReplication(boolean rawReplication)
+  {
+    checkInactive();
+    this.rawReplication = rawReplication;
+  }
+
+  public int getMaxRecommits()
+  {
+    return maxRecommits;
+  }
+
+  public void setMaxRecommits(int maxRecommits)
+  {
+    this.maxRecommits = maxRecommits;
+  }
+
+  public int getRecommitInterval()
+  {
+    return recommitInterval;
+  }
+
+  public void setRecommitInterval(int recommitInterval)
+  {
+    this.recommitInterval = recommitInterval;
+  }
+
+  @Override
+  protected String getThreadName()
+  {
+    return "RepositorySynchronizer"; //$NON-NLS-1$
+  }
+
+  @Override
+  protected BlockingQueue<Runnable> createQueue()
+  {
+    return new PriorityBlockingQueue<Runnable>();
+  }
+
+  @Override
+  protected void doBeforeActivate() throws Exception
+  {
+    super.doBeforeActivate();
+    checkState(remoteSessionConfigurationFactory, "remoteSessionConfigurationFactory"); //$NON-NLS-1$
+    checkState(localRepository, "localRepository"); //$NON-NLS-1$
+  }
+
+  @Override
+  protected void doAfterActivate() throws Exception
+  {
+    super.doAfterActivate();
+    scheduleConnect();
+  }
+
+  @Override
+  protected void doDeactivate() throws Exception
+  {
+    if (recommitTimer != null)
+    {
+      recommitTimer.cancel();
+      recommitTimer = null;
+    }
+
+    if (remoteSession != null)
+    {
+      remoteSession.removeListener(remoteSessionListener);
+      remoteSession.getBranchManager().removeListener(remoteSessionListener);
+      remoteSession.close();
+      remoteSession = null;
+    }
+
+    super.doDeactivate();
+  }
+
+  private void handleDisconnect()
+  {
+    OM.LOG.info("Disconnected from master.");
+    if (localRepository.getRootResourceID() == null)
+    {
+      localRepository.setState(CDOCommonRepository.State.INITIAL);
+    }
+    else
+    {
+      localRepository.setState(CDOCommonRepository.State.OFFLINE);
+    }
+
+    remoteSession.getBranchManager().removeListener(remoteSessionListener);
+    remoteSession.removeListener(remoteSessionListener);
+    remoteSession = null;
+
+    reconnect();
+  }
+
+  private void reconnect()
+  {
+    clearQueue();
+    if (isActive())
+    {
+      scheduleConnect();
+    }
+  }
+
+  private void scheduleConnect()
+  {
+    synchronized (connectLock)
+    {
+      if (localRepository.getState().isConnected())
+      {
+        return;
+      }
+
+      if (isActive())
+      {
+        addWork(new ConnectRunnable());
+      }
+    }
+  }
+
+  private void scheduleReplicate()
+  {
+    if (isActive())
+    {
+      addWork(new ReplicateRunnable());
+    }
+  }
+
+  private void sleepRetryInterval()
+  {
+    long end = System.currentTimeMillis() + 1000L * retryInterval;
+
+    for (;;)
+    {
+      long now = System.currentTimeMillis();
+      if (now >= end || !isActive())
+      {
+        break;
+      }
+
+      ConcurrencyUtil.sleep(Math.min(100L, end - now));
+    }
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  private final class RemoteSessionListener implements IListener
+  {
+    public void notifyEvent(IEvent event)
+    {
+      if (!isActive())
+      {
+        return;
+      }
+
+      if (event instanceof CDOBranchCreatedEvent)
+      {
+        CDOBranchCreatedEvent e = (CDOBranchCreatedEvent)event;
+        addWork(new BranchRunnable(e.getBranch()));
+      }
+      else if (event instanceof CDOSessionInvalidationEvent)
+      {
+        CDOSessionInvalidationEvent e = (CDOSessionInvalidationEvent)event;
+        if (e.isRemote())
+        {
+          addWork(new CommitRunnable(e));
+        }
+      }
+      else if (event instanceof CDOSessionLocksChangedEvent)
+      {
+        CDOSessionLocksChangedEvent e = (CDOSessionLocksChangedEvent)event;
+        addWork(new LocksRunnable(e));
+      }
+      else if (event instanceof ILifecycleEvent)
+      {
+        ILifecycleEvent e = (ILifecycleEvent)event;
+        if (e.getKind() == ILifecycleEvent.Kind.DEACTIVATED && e.getSource() == remoteSession)
+        {
+          handleDisconnect();
+        }
+      }
+    }
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  private static abstract class QueueRunnable implements Runnable, Comparable<QueueRunnable>
+  {
+    public int compareTo(QueueRunnable o)
+    {
+      return getPriority().compareTo(o.getPriority());
+    }
+
+    protected abstract Integer getPriority();
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  private final class ConnectRunnable extends QueueRunnable
+  {
+    public ConnectRunnable()
+    {
+    }
+
+    public void run()
+    {
+      synchronized (connectLock)
+      {
+        checkActive();
+        if (TRACER.isEnabled())
+        {
+          TRACER.trace("Connecting to master..."); //$NON-NLS-1$
+        }
+
+        try
+        {
+          CDOSessionConfiguration masterConfiguration = remoteSessionConfigurationFactory.createSessionConfiguration();
+          masterConfiguration.setPassiveUpdateMode(PassiveUpdateMode.ADDITIONS);
+          masterConfiguration.setLockNotificationMode(LockNotificationMode.ALWAYS);
+
+          remoteSession = (InternalCDOSession)masterConfiguration.openSession();
+
+          ensureNOOPRevisionCache();
+          setRootResourceID();
+        }
+        catch (Exception ex)
+        {
+          if (isActive())
+          {
+            OM.LOG.warn("Connection attempt failed. Retrying in " + retryInterval + " seconds...", ex);
+            sleepRetryInterval();
+            reconnect();
+          }
+
+          return;
+        }
+
+        OM.LOG.info("Connected to master.");
+        scheduleReplicate();
+
+        remoteSession.addListener(remoteSessionListener);
+        remoteSession.getBranchManager().addListener(remoteSessionListener);
+      }
+    }
+
+    @Override
+    protected Integer getPriority()
+    {
+      return CONNECT_PRIORITY;
+    }
+
+    private void setRootResourceID()
+    {
+      if (localRepository.getState() == CDOCommonRepository.State.INITIAL)
+      {
+        CDOID rootResourceID = remoteSession.getRepositoryInfo().getRootResourceID();
+        localRepository.setRootResourceID(rootResourceID);
+        localRepository.setState(CDOCommonRepository.State.OFFLINE);
+      }
+    }
+
+    private void ensureNOOPRevisionCache()
+    {
+      // Ensure that incoming revisions are not cached!
+      InternalCDORevisionCache cache = remoteSession.getRevisionManager().getCache();
+      if (!(cache instanceof NOOPRevisionCache))
+      {
+        throw new IllegalStateException("Master session does not use a NOOPRevisionCache: "
+            + cache.getClass().getName());
+      }
+    }
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  private final class ReplicateRunnable extends QueueRunnable
+  {
+    public ReplicateRunnable()
+    {
+    }
+
+    public void run()
+    {
+      try
+      {
+        checkActive();
+        if (TRACER.isEnabled())
+        {
+          TRACER.trace("Synchronizing with master..."); //$NON-NLS-1$
+        }
+
+        localRepository.setState(CDOCommonRepository.State.SYNCING);
+
+        CDOSessionProtocol sessionProtocol = remoteSession.getSessionProtocol();
+        OMMonitor monitor = new NotifyingMonitor("Synchronizing", getListeners());
+
+        if (isRawReplication())
+        {
+          sessionProtocol.replicateRepositoryRaw(localRepository, monitor);
+        }
+        else
+        {
+          sessionProtocol.replicateRepository(localRepository, monitor);
+        }
+
+        localRepository.setState(CDOCommonRepository.State.ONLINE);
+        OM.LOG.info("Synchronized with master.");
+      }
+      catch (RuntimeException ex)
+      {
+        if (isActive())
+        {
+          OM.LOG.warn("Replication attempt failed. Retrying in " + retryInterval + " seconds...", ex);
+          sleepRetryInterval();
+          handleDisconnect();
+        }
+      }
+    }
+
+    @Override
+    protected Integer getPriority()
+    {
+      return REPLICATE_PRIORITY;
+    }
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  private final class BranchRunnable extends QueueRunnable
+  {
+    private CDOBranch branch;
+
+    public BranchRunnable(CDOBranch branch)
+    {
+      this.branch = branch;
+    }
+
+    public void run()
+    {
+      localRepository.handleBranch(branch);
+    }
+
+    @Override
+    public int compareTo(QueueRunnable o)
+    {
+      int result = super.compareTo(o);
+      if (result == 0)
+      {
+        result = branch.compareTo(((BranchRunnable)o).branch);
+      }
+
+      return result;
+    }
+
+    @Override
+    protected Integer getPriority()
+    {
+      return BRANCH_PRIORITY;
+    }
+  }
+
+  private final class CommitRunnable extends RetryingRunnable
+  {
+    private CDOCommitInfo commitInfo;
+
+    public CommitRunnable(CDOCommitInfo commitInfo)
+    {
+      this.commitInfo = commitInfo;
+    }
+
+    @Override
+    protected void doRun()
+    {
+      localRepository.handleCommitInfo(commitInfo);
+    }
+
+    @Override
+    public int compareTo(QueueRunnable o)
+    {
+      int result = super.compareTo(o);
+      if (result == 0)
+      {
+        Long timeStamp = commitInfo.getTimeStamp();
+        Long timeStamp2 = ((CommitRunnable)o).commitInfo.getTimeStamp();
+        result = timeStamp < timeStamp2 ? -1 : timeStamp == timeStamp2 ? 0 : 1;
+      }
+
+      return result;
+    }
+
+    @Override
+    protected Integer getPriority()
+    {
+      return COMMIT_PRIORITY;
+    }
+
+    @Override
+    protected String getErrorMessage()
+    {
+      return "Replication of master commit failed:" + commitInfo;
+    }
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  private abstract class RetryingRunnable extends QueueRunnable
+  {
+    private List<Exception> failedRuns;
+
+    protected abstract void doRun();
+
+    protected abstract String getErrorMessage();
+
+    public void run()
+    {
+      try
+      {
+        doRun();
+      }
+      catch (Exception ex)
+      {
+        if (failedRuns == null)
+        {
+          failedRuns = new ArrayList<Exception>();
+        }
+
+        failedRuns.add(ex);
+        if (failedRuns.size() <= maxRecommits)
+        {
+          if (TRACER.isEnabled())
+          {
+            TRACER.format("Replication of master commit failed. Trying again in {0} seconds...", recommitInterval); //$NON-NLS-1$
+          }
+
+          if (recommitTimer == null)
+          {
+            recommitTimer = new Timer("RecommitTimer-" + RepositorySynchronizer.this);
+          }
+
+          recommitTimer.schedule(new TimerTask()
+          {
+            @Override
+            public void run()
+            {
+              try
+              {
+                addWork(this);
+              }
+              catch (Exception ex)
+              {
+                OM.LOG.error("CommitRunnableTask failed", ex);
+              }
+            }
+          }, recommitInterval * 1000L);
+        }
+        else
+        {
+          OM.LOG.error(getErrorMessage(), ex);
+        }
+      }
+    }
+  }
+
+  /**
+   * @author Caspar De Groot
+   */
+  private final class LocksRunnable extends RetryingRunnable
+  {
+    private CDOLockChangeInfo lockChangeInfo;
+
+    public LocksRunnable(CDOLockChangeInfo lockChangeInfo)
+    {
+      this.lockChangeInfo = lockChangeInfo;
+    }
+
+    @Override
+    protected Integer getPriority()
+    {
+      return LOCKS_PRIORITY;
+    }
+
+    @Override
+    protected void doRun()
+    {
+      try
+      {
+        StoreThreadLocal.setSession(localRepository.getReplicatorSession());
+        localRepository.handleLockChangeInfo(lockChangeInfo);
+      }
+      finally
+      {
+        StoreThreadLocal.release();
+      }
+    }
+
+    @Override
+    protected String getErrorMessage()
+    {
+      return "Replication of master lock changes failed:" + lockChangeInfo;
+    }
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/syncing/SynchronizableRepository.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/syncing/SynchronizableRepository.java
new file mode 100644
index 0000000..2276dc9
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/syncing/SynchronizableRepository.java
@@ -0,0 +1,788 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.internal.server.syncing;
+
+import org.eclipse.emf.cdo.common.CDOCommonRepository;
+import org.eclipse.emf.cdo.common.CDOCommonSession.Options.LockNotificationMode;
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.commit.CDOChangeSetData;
+import org.eclipse.emf.cdo.common.commit.CDOCommitData;
+import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
+import org.eclipse.emf.cdo.common.commit.CDOCommitInfoHandler;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.lob.CDOLob;
+import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
+import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo.Operation;
+import org.eclipse.emf.cdo.common.lock.CDOLockOwner;
+import org.eclipse.emf.cdo.common.lock.CDOLockState;
+import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockArea;
+import org.eclipse.emf.cdo.common.model.CDOPackageUnit;
+import org.eclipse.emf.cdo.common.protocol.CDODataInput;
+import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionKey;
+import org.eclipse.emf.cdo.common.util.CDOCommonUtil;
+import org.eclipse.emf.cdo.common.util.CDOException;
+import org.eclipse.emf.cdo.internal.common.commit.CDOCommitDataImpl;
+import org.eclipse.emf.cdo.internal.server.Repository;
+import org.eclipse.emf.cdo.internal.server.TransactionCommitContext;
+import org.eclipse.emf.cdo.internal.server.syncing.OfflineClone.CommitContextData;
+import org.eclipse.emf.cdo.server.IStoreAccessor;
+import org.eclipse.emf.cdo.server.StoreThreadLocal;
+import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranch;
+import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranchManager;
+import org.eclipse.emf.cdo.spi.common.commit.InternalCDOCommitInfoManager;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionCache;
+import org.eclipse.emf.cdo.spi.server.InternalCommitContext;
+import org.eclipse.emf.cdo.spi.server.InternalLockManager;
+import org.eclipse.emf.cdo.spi.server.InternalRepository;
+import org.eclipse.emf.cdo.spi.server.InternalRepositorySynchronizer;
+import org.eclipse.emf.cdo.spi.server.InternalSession;
+import org.eclipse.emf.cdo.spi.server.InternalSessionManager;
+import org.eclipse.emf.cdo.spi.server.InternalStore;
+import org.eclipse.emf.cdo.spi.server.InternalSynchronizableRepository;
+import org.eclipse.emf.cdo.spi.server.InternalTransaction;
+import org.eclipse.emf.cdo.spi.server.InternalView;
+import org.eclipse.emf.cdo.spi.server.SyncingUtil;
+
+import org.eclipse.net4j.util.WrappedException;
+import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
+import org.eclipse.net4j.util.lifecycle.LifecycleUtil;
+import org.eclipse.net4j.util.om.monitor.Monitor;
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+import org.eclipse.net4j.util.transaction.TransactionException;
+
+import org.eclipse.emf.spi.cdo.CDOSessionProtocol;
+import org.eclipse.emf.spi.cdo.CDOSessionProtocol.CommitTransactionResult;
+import org.eclipse.emf.spi.cdo.CDOSessionProtocol.LockObjectsResult;
+import org.eclipse.emf.spi.cdo.CDOSessionProtocol.UnlockObjectsResult;
+import org.eclipse.emf.spi.cdo.InternalCDOSession;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
+
+/**
+ * TODO:
+ * <ul>
+ * <li>Handle new package units that had been committed during offline (testDisconnectAndCommitAndMergeWithNewPackages).
+ * <li>Make CDOIDs of new objects temporary when merging out of temp branch.
+ * <li>Provide custom branching strategies.
+ * <li>Consider non-auditing masters.
+ * <li>Test out-of-order commits.
+ * <li>Don't create branches table if branching not supported.
+ * <li>Implement raw replication for NUMERIC and DECIMAL.
+ * <li>Notify new branches during raw replication.
+ * </ul>
+ * 
+ * @author Eike Stepper
+ */
+public abstract class SynchronizableRepository extends Repository.Default implements InternalSynchronizableRepository
+{
+  protected static final CDOCommonRepository.Type MASTER = CDOCommonRepository.Type.MASTER;
+
+  protected static final CDOCommonRepository.Type BACKUP = CDOCommonRepository.Type.BACKUP;
+
+  protected static final CDOCommonRepository.Type CLONE = CDOCommonRepository.Type.CLONE;
+
+  protected static final CDOCommonRepository.State INITIAL = CDOCommonRepository.State.INITIAL;
+
+  protected static final CDOCommonRepository.State OFFLINE = CDOCommonRepository.State.OFFLINE;
+
+  protected static final CDOCommonRepository.State SYNCING = CDOCommonRepository.State.SYNCING;
+
+  protected static final CDOCommonRepository.State ONLINE = CDOCommonRepository.State.ONLINE;
+
+  private static final String PROP_LAST_REPLICATED_BRANCH_ID = "org.eclipse.emf.cdo.server.lastReplicatedBranchID"; //$NON-NLS-1$
+
+  private static final String PROP_LAST_REPLICATED_COMMIT_TIME = "org.eclipse.emf.cdo.server.lastReplicatedCommitTime"; //$NON-NLS-1$
+
+  private static final String PROP_GRACEFULLY_SHUT_DOWN = "org.eclipse.emf.cdo.server.gracefullyShutDown"; //$NON-NLS-1$
+
+  private InternalRepositorySynchronizer synchronizer;
+
+  private InternalSession replicatorSession;
+
+  private int lastReplicatedBranchID = CDOBranch.MAIN_BRANCH_ID;
+
+  private long lastReplicatedCommitTime = CDOBranchPoint.UNSPECIFIED_DATE;
+
+  private int lastTransactionID;
+
+  private ReadLock writeThroughCommitLock;
+
+  private WriteLock handleCommitInfoLock;
+
+  public SynchronizableRepository()
+  {
+    ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
+    writeThroughCommitLock = rwLock.readLock();
+    handleCommitInfoLock = rwLock.writeLock();
+  }
+
+  public InternalRepositorySynchronizer getSynchronizer()
+  {
+    return synchronizer;
+  }
+
+  public void setSynchronizer(InternalRepositorySynchronizer synchronizer)
+  {
+    checkInactive();
+    this.synchronizer = synchronizer;
+  }
+
+  public InternalSession getReplicatorSession()
+  {
+    return replicatorSession;
+  }
+
+  @Override
+  public Object[] getElements()
+  {
+    List<Object> list = Arrays.asList(super.getElements());
+    list.add(synchronizer);
+    return list.toArray();
+  }
+
+  public int getLastReplicatedBranchID()
+  {
+    return lastReplicatedBranchID;
+  }
+
+  public void setLastReplicatedBranchID(int lastReplicatedBranchID)
+  {
+    if (this.lastReplicatedBranchID < lastReplicatedBranchID)
+    {
+      this.lastReplicatedBranchID = lastReplicatedBranchID;
+    }
+  }
+
+  public long getLastReplicatedCommitTime()
+  {
+    return lastReplicatedCommitTime;
+  }
+
+  public void setLastReplicatedCommitTime(long lastReplicatedCommitTime)
+  {
+    if (this.lastReplicatedCommitTime < lastReplicatedCommitTime)
+    {
+      this.lastReplicatedCommitTime = lastReplicatedCommitTime;
+    }
+  }
+
+  public String[] getLockAreaIDs()
+  {
+    try
+    {
+      StoreThreadLocal.setSession(replicatorSession);
+      final List<String> areaIDs = new LinkedList<String>();
+      getLockManager().getLockAreas(null, new LockArea.Handler()
+      {
+        public boolean handleLockArea(LockArea area)
+        {
+          areaIDs.add(area.getDurableLockingID());
+          return true;
+        }
+      });
+      return areaIDs.toArray(new String[areaIDs.size()]);
+    }
+    finally
+    {
+      StoreThreadLocal.release();
+    }
+  }
+
+  public void handleBranch(CDOBranch branch)
+  {
+    if (branch.isLocal())
+    {
+      return;
+    }
+
+    int branchID = branch.getID();
+    String name = branch.getName();
+
+    CDOBranchPoint base = branch.getBase();
+    InternalCDOBranch baseBranch = (InternalCDOBranch)base.getBranch();
+    long baseTimeStamp = base.getTimeStamp();
+
+    InternalCDOBranchManager branchManager = getBranchManager();
+    branchManager.createBranch(branchID, name, baseBranch, baseTimeStamp);
+    setLastReplicatedBranchID(branchID);
+  }
+
+  public void handleCommitInfo(CDOCommitInfo commitInfo)
+  {
+    CDOBranch branch = commitInfo.getBranch();
+    if (branch.isLocal())
+    {
+      return;
+    }
+
+    long timeStamp = commitInfo.getTimeStamp();
+    CDOBranchPoint head = branch.getHead();
+
+    InternalTransaction transaction = replicatorSession.openTransaction(++lastTransactionID, head);
+    ReplicatorCommitContext commitContext = new ReplicatorCommitContext(transaction, commitInfo);
+    commitContext.preWrite();
+    boolean success = false;
+
+    try
+    {
+      handleCommitInfoLock.lock();
+
+      commitContext.write(new Monitor());
+      commitContext.commit(new Monitor());
+
+      setLastCommitTimeStamp(timeStamp);
+      setLastReplicatedCommitTime(timeStamp);
+      success = true;
+    }
+    finally
+    {
+      handleCommitInfoLock.unlock();
+      commitContext.postCommit(success);
+      transaction.close();
+    }
+  }
+
+  public void handleLockChangeInfo(CDOLockChangeInfo lockChangeInfo)
+  {
+    CDOLockOwner owner = lockChangeInfo.getLockOwner();
+    String durableLockingID = owner.getDurableLockingID();
+    CDOBranch viewedBranch = lockChangeInfo.getBranch();
+    InternalLockManager lockManager = getLockManager();
+    LockType lockType = lockChangeInfo.getLockType();
+
+    InternalView view = null;
+
+    try
+    {
+      view = SyncingUtil.openViewWithLockArea(replicatorSession, lockManager, viewedBranch, durableLockingID);
+      List<Object> lockables = new LinkedList<Object>();
+
+      for (CDOLockState lockState : lockChangeInfo.getLockStates())
+      {
+        lockables.add(lockState.getLockedObject());
+      }
+
+      if (lockChangeInfo.getOperation() == Operation.LOCK)
+      {
+        // If we can't lock immediately, there's a conflict, which means we're in big
+        // trouble: somehow locks were obtained on the clone but not on the master. What to do?
+        // TODO (CD) Consider this problem further
+        //
+        long timeout = 0;
+        super.lock(view, lockType, lockables, null, timeout);
+      }
+      else if (lockChangeInfo.getOperation() == Operation.UNLOCK)
+      {
+        super.doUnlock(view, lockType, lockables);
+      }
+      else
+      {
+        throw new IllegalStateException("Unexpected: " + lockChangeInfo.getOperation());
+      }
+    }
+    finally
+    {
+      LifecycleUtil.deactivate(view);
+    }
+  }
+
+  public boolean handleLockArea(LockArea area)
+  {
+    try
+    {
+      StoreThreadLocal.setSession(replicatorSession);
+      getLockManager().updateLockArea(area);
+
+      // TODO (CD) getSessionManager().sendLockNotification(sender, lockChangeInfo);
+      return true;
+    }
+    finally
+    {
+      StoreThreadLocal.release();
+    }
+  }
+
+  public void replicateRaw(CDODataInput in, OMMonitor monitor) throws IOException
+  {
+    try
+    {
+      int fromBranchID = lastReplicatedBranchID + 1;
+      int toBranchID = in.readInt();
+      long fromCommitTime = lastReplicatedCommitTime + 1L;
+      long toCommitTime = in.readLong();
+
+      StoreThreadLocal.setSession(replicatorSession);
+      IStoreAccessor.Raw accessor = (IStoreAccessor.Raw)StoreThreadLocal.getAccessor();
+      accessor.rawImport(in, fromBranchID, toBranchID, fromCommitTime, toCommitTime, monitor);
+
+      replicateRawReviseRevisions();
+      replicateRawNotifyClients(lastReplicatedCommitTime, toCommitTime);
+
+      setLastReplicatedBranchID(toBranchID);
+      setLastReplicatedCommitTime(toCommitTime);
+      setLastCommitTimeStamp(toCommitTime);
+    }
+    finally
+    {
+      StoreThreadLocal.release();
+    }
+  }
+
+  public void goOnline()
+  {
+    if (getState() == OFFLINE)
+    {
+      LifecycleUtil.activate(synchronizer);
+      // Do not set the state to ONLINE yet; the synchronizer will set it to SYNCING first,
+      // and then to ONLINE after a succesful replication.
+    }
+  }
+
+  public void goOffline()
+  {
+    if (getState() != OFFLINE)
+    {
+      LifecycleUtil.deactivate(synchronizer);
+      setState(OFFLINE);
+    }
+  }
+
+  private void replicateRawReviseRevisions()
+  {
+    InternalCDORevisionCache cache = getRevisionManager().getCache();
+    for (CDORevision revision : cache.getCurrentRevisions())
+    {
+      cache.removeRevision(revision.getID(), revision);
+    }
+  }
+
+  private void replicateRawNotifyClients(long fromCommitTime, long toCommitTime)
+  {
+    InternalCDOCommitInfoManager manager = getCommitInfoManager();
+    InternalSessionManager sessionManager = getSessionManager();
+
+    Map<CDOBranch, TimeRange> branches = replicateRawGetBranches(fromCommitTime, toCommitTime);
+    for (Entry<CDOBranch, TimeRange> entry : branches.entrySet())
+    {
+      CDOBranch branch = entry.getKey();
+      TimeRange range = entry.getValue();
+      fromCommitTime = range.getTime1();
+      toCommitTime = range.getTime2();
+
+      CDOBranchPoint startPoint = branch.getPoint(fromCommitTime);
+      CDOBranchPoint endPoint = branch.getPoint(toCommitTime);
+      CDOChangeSetData changeSet = getChangeSet(startPoint, endPoint);
+
+      List<CDOPackageUnit> newPackages = Collections.emptyList(); // TODO Notify about new packages
+      List<CDOIDAndVersion> newObjects = changeSet.getNewObjects();
+      List<CDORevisionKey> changedObjects = changeSet.getChangedObjects();
+      List<CDOIDAndVersion> detachedObjects = changeSet.getDetachedObjects();
+      CDOCommitData data = new CDOCommitDataImpl(newPackages, newObjects, changedObjects, detachedObjects);
+
+      String comment = "<replicate raw commits>"; //$NON-NLS-1$
+      CDOCommitInfo commitInfo = manager.createCommitInfo(branch, toCommitTime, fromCommitTime, SYSTEM_USER_ID,
+          comment, data);
+      sessionManager.sendCommitNotification(replicatorSession, commitInfo);
+    }
+  }
+
+  private Map<CDOBranch, TimeRange> replicateRawGetBranches(long fromCommitTime, long toCommitTime)
+  {
+    final Map<CDOBranch, TimeRange> branches = new HashMap<CDOBranch, TimeRange>();
+    CDOCommitInfoHandler handler = new CDOCommitInfoHandler()
+    {
+      public void handleCommitInfo(CDOCommitInfo commitInfo)
+      {
+        CDOBranch branch = commitInfo.getBranch();
+        long timeStamp = commitInfo.getTimeStamp();
+        TimeRange range = branches.get(branch);
+        if (range == null)
+        {
+          branches.put(branch, new TimeRange(timeStamp));
+        }
+        else
+        {
+          range.update(timeStamp);
+        }
+      }
+    };
+
+    getCommitInfoManager().getCommitInfos(null, fromCommitTime, toCommitTime, handler);
+    return branches;
+  }
+
+  @Override
+  public abstract InternalCommitContext createCommitContext(InternalTransaction transaction);
+
+  protected InternalCommitContext createNormalCommitContext(InternalTransaction transaction)
+  {
+    return super.createCommitContext(transaction);
+  }
+
+  protected InternalCommitContext createWriteThroughCommitContext(InternalTransaction transaction)
+  {
+    return new WriteThroughCommitContext(transaction);
+  }
+
+  @Override
+  protected void doBeforeActivate() throws Exception
+  {
+    super.doBeforeActivate();
+    checkState(synchronizer, "synchronizer"); //$NON-NLS-1$
+  }
+
+  @Override
+  protected void doActivate() throws Exception
+  {
+    super.doActivate();
+
+    InternalStore store = getStore();
+    if (!store.isFirstStart())
+    {
+      Map<String, String> map = store.getPersistentProperties(Collections.singleton(PROP_GRACEFULLY_SHUT_DOWN));
+      if (!map.containsKey(PROP_GRACEFULLY_SHUT_DOWN))
+      {
+        setReplicationCountersToLatest();
+      }
+      else
+      {
+        Set<String> names = new HashSet<String>();
+        names.add(PROP_LAST_REPLICATED_BRANCH_ID);
+        names.add(PROP_LAST_REPLICATED_COMMIT_TIME);
+
+        map = store.getPersistentProperties(names);
+        setLastReplicatedBranchID(Integer.valueOf(map.get(PROP_LAST_REPLICATED_BRANCH_ID)));
+        setLastReplicatedCommitTime(Long.valueOf(map.get(PROP_LAST_REPLICATED_COMMIT_TIME)));
+      }
+    }
+
+    store.removePersistentProperties(Collections.singleton(PROP_GRACEFULLY_SHUT_DOWN));
+
+    if (getType() != MASTER)
+    {
+      startSynchronization();
+    }
+  }
+
+  @Override
+  protected void doDeactivate() throws Exception
+  {
+    stopSynchronization();
+
+    Map<String, String> map = new HashMap<String, String>();
+    map.put(PROP_LAST_REPLICATED_BRANCH_ID, Integer.toString(lastReplicatedBranchID));
+    map.put(PROP_LAST_REPLICATED_COMMIT_TIME, Long.toString(lastReplicatedCommitTime));
+    map.put(PROP_GRACEFULLY_SHUT_DOWN, Boolean.TRUE.toString());
+
+    InternalStore store = getStore();
+    store.setPersistentProperties(map);
+
+    super.doDeactivate();
+  }
+
+  protected void startSynchronization()
+  {
+    replicatorSession = getSessionManager().openSession(null);
+    replicatorSession.options().setPassiveUpdateEnabled(false);
+    replicatorSession.options().setLockNotificationMode(LockNotificationMode.OFF);
+
+    synchronizer.setLocalRepository(this);
+    synchronizer.activate();
+  }
+
+  protected void stopSynchronization()
+  {
+    if (synchronizer != null)
+    {
+      synchronizer.deactivate();
+    }
+  }
+
+  protected void setReplicationCountersToLatest()
+  {
+    setLastReplicatedBranchID(getStore().getLastBranchID());
+    setLastReplicatedCommitTime(getStore().getLastNonLocalCommitTime());
+  }
+
+  protected void doInitRootResource()
+  {
+    super.initRootResource();
+  }
+
+  @Override
+  protected void initRootResource()
+  {
+    setState(INITIAL);
+  }
+
+  @Override
+  public LockObjectsResult lock(InternalView view, LockType lockType, List<CDORevisionKey> revisionKeys, long timeout)
+  {
+    if (view.getBranch().isLocal())
+    {
+      return super.lock(view, lockType, revisionKeys, timeout);
+    }
+
+    if (getState() != ONLINE)
+    {
+      throw new CDOException("Cannot lock in a non-local branch when clone is not connected to master");
+    }
+
+    return lockThrough(view, lockType, revisionKeys, timeout);
+  }
+
+  private LockObjectsResult lockOnMaster(InternalView view, LockType type, List<CDORevisionKey> revKeys, long timeout)
+      throws InterruptedException
+  {
+    // Delegate locking to the master
+    InternalCDOSession remoteSession = getSynchronizer().getRemoteSession();
+    CDOSessionProtocol sessionProtocol = remoteSession.getSessionProtocol();
+
+    String areaID = view.getDurableLockingID();
+    if (areaID == null)
+    {
+      throw new IllegalStateException("Durable locking is not enabled.");
+    }
+
+    LockObjectsResult masterLockingResult = sessionProtocol.delegateLockObjects(areaID, revKeys, view.getBranch(),
+        type, timeout);
+
+    if (masterLockingResult.isSuccessful() && masterLockingResult.isWaitForUpdate())
+    {
+      if (!getSynchronizer().getRemoteSession().options().isPassiveUpdateEnabled())
+      {
+        throw new AssertionError(
+            "Master lock result requires clone to wait, but clone does not have passiveUpdates enabled.");
+      }
+
+      long requiredTimestamp = masterLockingResult.getRequiredTimestamp();
+      remoteSession.waitForUpdate(requiredTimestamp);
+    }
+
+    return masterLockingResult;
+  }
+
+  private LockObjectsResult lockThrough(InternalView view, LockType type, List<CDORevisionKey> keys, long timeout)
+  {
+    try
+    {
+      LockObjectsResult masterLockingResult = lockOnMaster(view, type, keys, timeout);
+      if (!masterLockingResult.isSuccessful())
+      {
+        return masterLockingResult;
+      }
+
+      LockObjectsResult localLockingResult = super.lock(view, type, keys, timeout);
+      return localLockingResult;
+    }
+    catch (InterruptedException ex)
+    {
+      throw WrappedException.wrap(ex);
+    }
+  }
+
+  @Override
+  public UnlockObjectsResult unlock(InternalView view, LockType lockType, List<CDOID> objectIDs)
+  {
+    if (view.getBranch().isLocal())
+    {
+      super.unlock(view, lockType, objectIDs);
+    }
+
+    if (getState() != ONLINE)
+    {
+      throw new CDOException("Cannot unlock in a non-local branch when clone is not connected to master");
+    }
+
+    return unlockThrough(view, lockType, objectIDs);
+  }
+
+  private void unlockOnMaster(InternalView view, LockType lockType, List<CDOID> objectIDs)
+  {
+    InternalCDOSession remoteSession = getSynchronizer().getRemoteSession();
+    CDOSessionProtocol sessionProtocol = remoteSession.getSessionProtocol();
+
+    String lockAreaID = view.getDurableLockingID();
+    if (lockAreaID == null)
+    {
+      throw new IllegalStateException("Durable locking is not enabled.");
+    }
+
+    sessionProtocol.delegateUnlockObjects(lockAreaID, objectIDs, lockType);
+  }
+
+  private UnlockObjectsResult unlockThrough(InternalView view, LockType lockType, List<CDOID> objectIDs)
+  {
+    unlockOnMaster(view, lockType, objectIDs);
+    return super.unlock(view, lockType, objectIDs);
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  private static final class TimeRange
+  {
+    private long time1;
+
+    private long time2;
+
+    public TimeRange(long time)
+    {
+      time1 = time;
+      time2 = time;
+    }
+
+    public void update(long time)
+    {
+      if (time < time1)
+      {
+        time1 = time;
+      }
+
+      if (time > time2)
+      {
+        time2 = time;
+      }
+    }
+
+    public long getTime1()
+    {
+      return time1;
+    }
+
+    public long getTime2()
+    {
+      return time2;
+    }
+
+    @Override
+    public String toString()
+    {
+      return "[" + CDOCommonUtil.formatTimeStamp(time1) + " - " + CDOCommonUtil.formatTimeStamp(time1) + "]";
+    }
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  protected final class WriteThroughCommitContext extends TransactionCommitContext
+  {
+    public WriteThroughCommitContext(InternalTransaction transaction)
+    {
+      super(transaction);
+    }
+
+    @Override
+    public void preWrite()
+    {
+      // Do nothing
+    }
+
+    @Override
+    public void write(OMMonitor monitor)
+    {
+      // Do nothing
+    }
+
+    @Override
+    public void commit(OMMonitor monitor)
+    {
+      InternalTransaction transaction = getTransaction();
+
+      // Prepare commit to the master
+      CDOBranch branch = transaction.getBranch();
+      String userID = getUserID();
+      String comment = getCommitComment();
+      CDOCommitData commitData = new CommitContextData(this);
+      Collection<CDOLob<?>> lobs = Collections.emptySet();
+
+      // Delegate commit to the master
+      CDOSessionProtocol sessionProtocol = getSynchronizer().getRemoteSession().getSessionProtocol();
+      CommitTransactionResult result = sessionProtocol.commitDelegation(branch, userID, comment, commitData,
+          getDetachedObjectTypes(), lobs, monitor);
+
+      // Stop if commit to master failed
+      String rollbackMessage = result.getRollbackMessage();
+      if (rollbackMessage != null)
+      {
+        throw new TransactionException(rollbackMessage);
+      }
+
+      // Prepare data needed for commit result and commit notifications
+      long timeStamp = result.getTimeStamp();
+      setTimeStamp(timeStamp);
+      addIDMappings(result.getIDMappings());
+      applyIDMappings(new Monitor());
+
+      try
+      {
+        writeThroughCommitLock.lock();
+
+        // Commit to the local repository
+        super.preWrite();
+        super.write(new Monitor());
+        super.commit(new Monitor());
+      }
+      finally
+      {
+        writeThroughCommitLock.unlock();
+      }
+
+      // Remember commit time in the local repository
+      setLastCommitTimeStamp(timeStamp);
+      setLastReplicatedCommitTime(timeStamp);
+
+      // Remember commit time in the replicator session.
+      getSynchronizer().getRemoteSession().setLastUpdateTime(timeStamp);
+    }
+
+    @Override
+    protected long[] createTimeStamp(OMMonitor monitor)
+    {
+      // Already set after commit to the master.
+      // Do not call getTimeStamp() of the enclosing Repo class!!!
+      InternalRepository repository = getTransaction().getSession().getManager().getRepository();
+      return repository.forceCommitTimeStamp(WriteThroughCommitContext.this.getTimeStamp(), monitor);
+    }
+
+    @Override
+    protected void lockObjects() throws InterruptedException
+    {
+      // Do nothing
+    }
+
+    private void addIDMappings(Map<CDOID, CDOID> idMappings)
+    {
+      for (Map.Entry<CDOID, CDOID> idMapping : idMappings.entrySet())
+      {
+        CDOID oldID = idMapping.getKey();
+        CDOID newID = idMapping.getValue();
+        addIDMapping(oldID, newID);
+      }
+    }
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/CDOServerBrowser.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/CDOServerBrowser.java
new file mode 100644
index 0000000..ed7ec5e
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/CDOServerBrowser.java
@@ -0,0 +1,1220 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
+import org.eclipse.emf.cdo.common.commit.CDOCommitInfoHandler;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.lob.CDOLobHandler;
+import org.eclipse.emf.cdo.common.revision.CDOAllRevisionsProvider;
+import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionKey;
+import org.eclipse.emf.cdo.common.revision.CDORevisionUtil;
+import org.eclipse.emf.cdo.common.revision.CDORevisionUtil.AllRevisionsDumper;
+import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
+import org.eclipse.emf.cdo.common.util.CDOCommonUtil;
+import org.eclipse.emf.cdo.internal.server.bundle.OM;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageInfo;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit;
+import org.eclipse.emf.cdo.spi.common.revision.DetachedCDORevision;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+import org.eclipse.emf.cdo.spi.common.revision.PointerCDORevision;
+import org.eclipse.emf.cdo.spi.common.revision.SyntheticCDORevision;
+import org.eclipse.emf.cdo.spi.server.InternalRepository;
+
+import org.eclipse.net4j.util.HexUtil;
+import org.eclipse.net4j.util.StringUtil;
+import org.eclipse.net4j.util.WrappedException;
+import org.eclipse.net4j.util.concurrent.Worker;
+import org.eclipse.net4j.util.container.ContainerEventAdapter;
+import org.eclipse.net4j.util.container.IContainer;
+import org.eclipse.net4j.util.container.IPluginContainer;
+import org.eclipse.net4j.util.event.IListener;
+import org.eclipse.net4j.util.factory.ProductCreationException;
+
+import org.eclipse.emf.ecore.EClassifier;
+import org.eclipse.emf.ecore.EDataType;
+import org.eclipse.emf.ecore.EEnum;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.CharArrayWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.io.Writer;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author Eike Stepper
+ * @since 4.0
+ */
+public class CDOServerBrowser extends Worker
+{
+  private static final String REQUEST_PREFIX = "GET ";
+
+  private static final String REQUEST_SUFFIX = " HTTP/1.1";
+
+  private ThreadLocal<Map<String, String>> params = new InheritableThreadLocal<Map<String, String>>()
+  {
+    @Override
+    protected Map<String, String> initialValue()
+    {
+      return new HashMap<String, String>();
+    }
+  };
+
+  private int port = 7777;
+
+  private ServerSocket serverSocket;
+
+  private Map<String, InternalRepository> repositories;
+
+  private List<Page> pages = new ArrayList<Page>();
+
+  public CDOServerBrowser(Map<String, InternalRepository> repositories)
+  {
+    this.repositories = repositories;
+    setDaemon(true);
+  }
+
+  public Map<String, InternalRepository> getRepositories()
+  {
+    return repositories;
+  }
+
+  public int getPort()
+  {
+    return port;
+  }
+
+  public void setPort(int port)
+  {
+    this.port = port;
+  }
+
+  @Override
+  protected void work(WorkContext context) throws Exception
+  {
+    Socket socket = null;
+
+    try
+    {
+      socket = serverSocket.accept();
+      BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
+      OutputStream out = new BufferedOutputStream(socket.getOutputStream());
+      PrintStream pout = new PrintStream(out);
+      printHeader(pout);
+
+      String line;
+      while ((line = in.readLine()) != null)
+      {
+        if (line.startsWith(REQUEST_PREFIX) && line.endsWith(REQUEST_SUFFIX))
+        {
+          String request = line.substring(REQUEST_PREFIX.length(), line.length() - REQUEST_SUFFIX.length()).trim();
+          String resource = request;
+          String params = "";
+          int pos = request.indexOf('?');
+          if (pos != -1)
+          {
+            resource = request.substring(0, pos);
+            params = request.substring(pos + 1);
+          }
+
+          initParams(params);
+          if ("/".equals(resource))
+          {
+            showMenu(pout);
+          }
+          else
+          {
+            String pageName = resource.substring(1);
+            for (Page page : pages)
+            {
+              if (page.getName().equals(pageName))
+              {
+                showPage(pout, page);
+              }
+            }
+          }
+        }
+
+        out.flush();
+        return;
+      }
+    }
+    catch (Exception ex)
+    {
+      if (isActive())
+      {
+        ex.printStackTrace();
+      }
+    }
+    finally
+    {
+      params.remove();
+      if (socket != null)
+      {
+        socket.close();
+      }
+    }
+  }
+
+  protected void initParams(String params)
+  {
+    Map<String, String> map = this.params.get();
+    for (String param : params.split("&"))
+    {
+      if (param.length() != 0)
+      {
+        String[] keyValue = param.split("=");
+        map.put(keyValue[0], keyValue[1]);
+      }
+    }
+  }
+
+  protected void clearParams()
+  {
+    Map<String, String> map = params.get();
+    map.clear();
+  }
+
+  public void removeParam(String key)
+  {
+    Map<String, String> map = params.get();
+    map.remove(key);
+  }
+
+  public String getParam(String key)
+  {
+    Map<String, String> map = params.get();
+    return map.get(key);
+  }
+
+  public String href(String label, String resource, String... params)
+  {
+    Map<String, String> map = new HashMap<String, String>(this.params.get());
+    for (int i = 0; i < params.length;)
+    {
+      map.put(params[i++], params[i++]);
+    }
+
+    List<String> list = new ArrayList<String>(map.keySet());
+    Collections.sort(list);
+
+    StringBuilder builder = new StringBuilder();
+    for (String key : list)
+    {
+      String value = map.get(key);
+      if (value != null)
+      {
+        if (builder.length() != 0)
+        {
+          builder.append("&");
+        }
+
+        builder.append(key);
+        builder.append("=");
+        builder.append(value);
+      }
+    }
+
+    return "<a href=\"/" + escape(resource) + "?" + escape(builder.toString()) + "\">" + escape(label) + "</a>";
+  }
+
+  public String escape(String raw)
+  {
+    if (raw == null)
+    {
+      return "null";
+    }
+
+    return raw.replace("<", "&lt;");
+  }
+
+  protected void printHeader(PrintStream pout)
+  {
+    pout.print("HTTP/1.1 200 OK\r\n");
+    pout.print("Content-Type: text/html\r\n");
+    pout.print("Date: " + new Date() + "\r\n");
+    pout.print("Server: DBBrowser 3.0\r\n");
+    pout.print("\r\n");
+  }
+
+  protected void showMenu(PrintStream pout)
+  {
+    clearParams();
+    pout.print("<h1>CDO Server Browser 4.0</h1><hr>\r\n");
+
+    for (Page page : pages)
+    {
+      pout.println("<h3>" + href(page.getLabel(), page.getName()) + "</h3>");
+    }
+  }
+
+  protected void showPage(PrintStream pout, Page page)
+  {
+    String repo = getParam("repo");
+
+    List<String> repoNames = new ArrayList<String>(getRepositoryNames());
+    Collections.sort(repoNames);
+
+    pout.print("<h3><a href=\"/\">" + page.getLabel() + "</a>:&nbsp;&nbsp;");
+    for (String repoName : repoNames)
+    {
+      InternalRepository repository = getRepository(repoName);
+      if (!page.canDisplay(repository))
+      {
+        continue;
+      }
+
+      if (repo == null)
+      {
+        repo = repoName;
+      }
+
+      if (repoName.equals(repo))
+      {
+        pout.print("<b>" + escape(repoName) + "</b>&nbsp;&nbsp;");
+      }
+      else
+      {
+        pout.print(href(repoName, page.getName(), "repo", repoName) + "&nbsp;&nbsp;");
+      }
+    }
+
+    pout.print("</h3>");
+
+    InternalRepository repository = getRepository(repo);
+    if (repository != null)
+    {
+      pout.print("<p>\r\n");
+      page.display(this, repository, pout);
+    }
+  }
+
+  protected Set<String> getRepositoryNames()
+  {
+    return repositories.keySet();
+  }
+
+  protected InternalRepository getRepository(String name)
+  {
+    return repositories.get(name);
+  }
+
+  @Override
+  protected String getThreadName()
+  {
+    return "DBBrowser";
+  }
+
+  protected void initPages(List<Page> pages)
+  {
+    pages.add(new PackagesPage());
+    pages.add(new RevisionsPage.FromCache());
+    pages.add(new RevisionsPage.FromStore());
+    pages.add(new LobsPage());
+    pages.add(new HistoryPage());
+
+    IPluginContainer container = IPluginContainer.INSTANCE;
+    Set<String> factoryTypes = container.getFactoryTypes(Page.PRODUCT_GROUP);
+    for (String factoryType : factoryTypes)
+    {
+      Page page = (Page)container.getElement(Page.PRODUCT_GROUP, factoryType, null);
+      pages.add(page);
+    }
+  }
+
+  @Override
+  protected void doActivate() throws Exception
+  {
+    initPages(pages);
+
+    try
+    {
+      serverSocket = new ServerSocket(port);
+    }
+    catch (Exception ex)
+    {
+      throw new IllegalStateException("Could not open socket on port " + port, ex);
+    }
+
+    super.doActivate();
+  }
+
+  @Override
+  protected void doDeactivate() throws Exception
+  {
+    serverSocket.close();
+    super.doDeactivate();
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  public static class ContainerBased extends CDOServerBrowser
+  {
+    private IContainer<?> container;
+
+    private IListener containerListener = new ContainerEventAdapter<Object>()
+    {
+      @Override
+      protected void onAdded(IContainer<Object> container, Object element)
+      {
+        addElement(element);
+      }
+
+      @Override
+      protected void onRemoved(IContainer<Object> container, Object element)
+      {
+        removeElement(element);
+      }
+    };
+
+    public ContainerBased(IContainer<?> container)
+    {
+      super(new HashMap<String, InternalRepository>());
+      this.container = container;
+    }
+
+    public ContainerBased()
+    {
+      this(IPluginContainer.INSTANCE);
+    }
+
+    public IContainer<?> getContainer()
+    {
+      return container;
+    }
+
+    @Override
+    protected void doActivate() throws Exception
+    {
+      super.doActivate();
+      for (Object element : container.getElements())
+      {
+        addElement(element);
+      }
+
+      container.addListener(containerListener);
+    }
+
+    @Override
+    protected void doDeactivate() throws Exception
+    {
+      container.removeListener(containerListener);
+      super.doDeactivate();
+    }
+
+    private void addElement(Object element)
+    {
+      if (element instanceof InternalRepository)
+      {
+        InternalRepository repository = (InternalRepository)element;
+        getRepositories().put(repository.getName(), repository);
+      }
+    }
+
+    private void removeElement(Object element)
+    {
+      if (element instanceof InternalRepository)
+      {
+        InternalRepository repository = (InternalRepository)element;
+        getRepositories().remove(repository.getName());
+      }
+    }
+
+    /**
+     * @author Eike Stepper
+     */
+    public static class Factory extends org.eclipse.net4j.util.factory.Factory
+    {
+      public static final String PRODUCT_GROUP = "org.eclipse.emf.cdo.server.browsers";
+
+      public static final String TYPE = "default";
+
+      private IContainer<?> container;
+
+      public Factory()
+      {
+        this(IPluginContainer.INSTANCE);
+      }
+
+      public Factory(IContainer<?> container)
+      {
+        super(PRODUCT_GROUP, TYPE);
+        this.container = container;
+      }
+
+      public CDOServerBrowser.ContainerBased create(String description) throws ProductCreationException
+      {
+        CDOServerBrowser.ContainerBased browser = new CDOServerBrowser.ContainerBased(container);
+
+        try
+        {
+          if (!StringUtil.isEmpty(description))
+          {
+            browser.setPort(Integer.valueOf(description));
+          }
+        }
+        catch (Exception ex)
+        {
+          OM.LOG.warn(ex);
+        }
+
+        return browser;
+      }
+    }
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  public static interface Page
+  {
+    public static final String PRODUCT_GROUP = "org.eclipse.emf.cdo.server.browserPages";
+
+    public String getName();
+
+    public String getLabel();
+
+    public boolean canDisplay(InternalRepository repository);
+
+    public void display(CDOServerBrowser browser, InternalRepository repository, PrintStream out);
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  public static abstract class AbstractPage implements Page
+  {
+    private String name;
+
+    private String label;
+
+    public AbstractPage(String name, String label)
+    {
+      this.name = name;
+      this.label = label;
+    }
+
+    public String getName()
+    {
+      return name;
+    }
+
+    public String getLabel()
+    {
+      return label;
+    }
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  public static class PackagesPage extends AbstractPage
+  {
+    public static final String NAME = "packages";
+
+    public PackagesPage()
+    {
+      super(NAME, "Packages and Classes");
+    }
+
+    public boolean canDisplay(InternalRepository repository)
+    {
+      return true;
+    }
+
+    public void display(CDOServerBrowser browser, InternalRepository repository, PrintStream out)
+    {
+      String param = browser.getParam("classifier");
+      InternalCDOPackageRegistry packageRegistry = repository.getPackageRegistry(false);
+      for (InternalCDOPackageUnit unit : packageRegistry.getPackageUnits())
+      {
+        param = showPackage(unit.getTopLevelPackageInfo(), packageRegistry, browser, param, out, "&nbsp;&nbsp;");
+      }
+    }
+
+    protected String showPackage(InternalCDOPackageInfo info, InternalCDOPackageRegistry packageRegistry,
+        CDOServerBrowser browser, String param, PrintStream out, String prefix)
+    {
+      EPackage ePackage = info.getEPackage();
+      out.println("<h3>" + prefix + ePackage.getName() + "&nbsp;&nbsp;[" + ePackage.getNsURI() + "]</h3>");
+
+      for (EClassifier classifier : ePackage.getEClassifiers())
+      {
+        String name = classifier.getName();
+        if (param == null)
+        {
+          param = name;
+        }
+
+        String label = name.equals(param) ? name : browser.href(name, getName(), "classifier", name);
+        out.print(prefix + "&nbsp;&nbsp;<b>" + label);
+
+        if (classifier instanceof EEnum)
+        {
+          EEnum eenum = (EEnum)classifier;
+          out.print("&nbsp;&nbsp;" + eenum.getELiterals());
+        }
+        else if (classifier instanceof EDataType)
+        {
+          EDataType eDataType = (EDataType)classifier;
+          out.print("&nbsp;&nbsp;" + eDataType.getInstanceClassName());
+        }
+
+        out.println("</b><br>");
+      }
+
+      for (EPackage sub : ePackage.getESubpackages())
+      {
+        InternalCDOPackageInfo subInfo = packageRegistry.getPackageInfo(sub);
+        param = showPackage(subInfo, packageRegistry, browser, param, out, prefix + "&nbsp;&nbsp;");
+      }
+
+      return param;
+    }
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  public static abstract class RevisionsPage extends AbstractPage
+  {
+    public RevisionsPage(String name, String label)
+    {
+      super(name, label);
+    }
+
+    public void display(final CDOServerBrowser browser, InternalRepository repository, PrintStream out)
+    {
+      Map<CDOBranch, List<CDORevision>> allRevisions = getAllRevisions(repository);
+      Map<CDOID, List<CDORevision>> ids = getAllIDs(allRevisions);
+
+      out.print("<table border=\"0\">\r\n");
+      out.print("<tr>\r\n");
+
+      out.print("<td valign=\"top\">\r\n");
+      out.print("<table border=\"1\" cellpadding=\"2\"><tr><td>\r\n");
+      final String[] revision = { browser.getParam("revision") };
+      new AllRevisionsDumper.Stream.Html(allRevisions, out)
+      {
+        private StringBuilder versionsBuilder;
+
+        private CDORevision lastRevision;
+
+        @Override
+        protected void dumpEnd(List<CDOBranch> branches)
+        {
+          dumpLastRevision();
+          super.dumpEnd(branches);
+        }
+
+        @Override
+        protected void dumpBranch(CDOBranch branch)
+        {
+          dumpLastRevision();
+          super.dumpBranch(branch);
+        }
+
+        @Override
+        protected void dumpRevision(CDORevision rev)
+        {
+          CDOID id = rev.getID();
+          if (lastRevision != null && !id.equals(lastRevision.getID()))
+          {
+            dumpLastRevision();
+          }
+
+          if (versionsBuilder == null)
+          {
+            versionsBuilder = new StringBuilder();
+          }
+          else
+          {
+            versionsBuilder.append(" ");
+            if (versionsBuilder.length() > 64)
+            {
+              versionsBuilder.append("<br>");
+            }
+          }
+
+          String key = CDORevisionUtil.formatRevisionKey(rev);
+          if (revision[0] == null)
+          {
+            revision[0] = key;
+          }
+
+          String version = getVersionPrefix(rev) + rev.getVersion();
+          if (key.equals(revision[0]))
+          {
+            versionsBuilder.append("<b>" + version + "</b>");
+          }
+          else
+          {
+            versionsBuilder.append(browser.href(version, getName(), "revision", key));
+          }
+
+          lastRevision = rev;
+        }
+
+        protected void dumpLastRevision()
+        {
+          if (versionsBuilder != null)
+          {
+            PrintStream out = out();
+            out.println("<tr>");
+            out.println("<td valign=\"top\">&nbsp;&nbsp;&nbsp;&nbsp;");
+            out.println(getCDOIDLabel(lastRevision));
+            out.println("&nbsp;&nbsp;&nbsp;&nbsp;</td>");
+
+            out.println("<td>");
+            out.println(versionsBuilder.toString());
+            out.println("</td>");
+            out.println("</tr>");
+
+            lastRevision = null;
+            versionsBuilder = null;
+          }
+        }
+      }.dump();
+
+      out.print("</td></tr></table></td>\r\n");
+      out.print("<td>&nbsp;&nbsp;&nbsp;</td>\r\n");
+
+      if (revision[0] != null)
+      {
+        out.print("<td valign=\"top\">\r\n");
+        showRevision(out, browser, allRevisions, ids, revision[0], repository);
+        out.print("</td>\r\n");
+      }
+
+      out.print("</tr>\r\n");
+      out.print("</table>\r\n");
+    }
+
+    /**
+     * @since 4.0
+     */
+    protected void showRevision(PrintStream pout, CDOServerBrowser browser,
+        Map<CDOBranch, List<CDORevision>> allRevisions, Map<CDOID, List<CDORevision>> ids, String key,
+        InternalRepository repository)
+    {
+      CDORevisionKey revisionKey = CDORevisionUtil.parseRevisionKey(key, repository.getBranchManager());
+      for (CDORevision revision : allRevisions.get(revisionKey.getBranch()))
+      {
+        if (revision.getVersion() == revisionKey.getVersion() && revision.getID().equals(revisionKey.getID()))
+        {
+          showRevision(pout, browser, ids, (InternalCDORevision)revision);
+          return;
+        }
+      }
+    }
+
+    /**
+     * @since 4.0
+     */
+    protected void showRevision(PrintStream pout, CDOServerBrowser browser, Map<CDOID, List<CDORevision>> ids,
+        InternalCDORevision revision)
+    {
+      String className = revision.getEClass().toString();
+      className = className.substring(className.indexOf(' '));
+      className = StringUtil.replace(className, new String[] { "(", ")", "," }, new String[] { "<br>", "", "<br>" });
+      className = className.substring("<br>".length() + 1);
+
+      String created = CDOCommonUtil.formatTimeStamp(revision.getTimeStamp());
+      String commitInfo = browser.href(created, HistoryPage.NAME, "time", String.valueOf(revision.getTimeStamp()));
+
+      pout.print("<table border=\"1\" cellpadding=\"2\">\r\n");
+      showKeyValue(pout, true, "type", "<b>" + revision.getClass().getSimpleName() + "</b>");
+      showKeyValue(pout, true, "class", className);
+      showKeyValue(pout, true, "id", getRevisionValue(revision.getID(), browser, ids, revision));
+      showKeyValue(pout, true, "branch", revision.getBranch().getName() + "[" + revision.getBranch().getID() + "]");
+      showKeyValue(pout, true, "version", revision.getVersion());
+      showKeyValue(pout, true, "created", commitInfo);
+      showKeyValue(pout, true, "revised", CDOCommonUtil.formatTimeStamp(revision.getRevised()));
+      if (!(revision instanceof SyntheticCDORevision))
+      {
+        showKeyValue(pout, true, "resource", getRevisionValue(revision.getResourceID(), browser, ids, revision));
+        showKeyValue(pout, true, "container", getRevisionValue(revision.getContainerID(), browser, ids, revision));
+        showKeyValue(pout, true, "feature", revision.getContainingFeatureID());
+
+        for (EStructuralFeature feature : revision.getClassInfo().getAllPersistentFeatures())
+        {
+          Object value = revision.getValue(feature);
+          showKeyValue(pout, false, feature.getName(), getRevisionValue(value, browser, ids, revision));
+        }
+      }
+
+      pout.print("</table>\r\n");
+    }
+
+    /**
+     * @since 4.0
+     */
+    protected Object getRevisionValue(Object value, CDOServerBrowser browser, Map<CDOID, List<CDORevision>> ids,
+        InternalCDORevision context)
+    {
+      if (value instanceof CDOID)
+      {
+        List<CDORevision> revisions = ids.get(value);
+        if (revisions != null)
+        {
+          StringBuilder builder = new StringBuilder();
+          builder.append(getCDOIDLabel(revisions.get(0)));
+
+          if (browser != null)
+          {
+            builder.append("&nbsp;&nbsp;");
+            for (CDORevision revision : revisions)
+            {
+              String label = getVersionPrefix(revision) + revision.getVersion();
+              String branchName = revision.getBranch().getName();
+              if (!CDOBranch.MAIN_BRANCH_NAME.equals(branchName))
+              {
+                label += "[" + branchName + "]";
+              }
+
+              builder.append(" ");
+              if (revision == context)
+              {
+                builder.append(label);
+              }
+              else
+              {
+                builder.append(browser.href(label, getName(), "revision", CDORevisionUtil.formatRevisionKey(revision)));
+              }
+            }
+          }
+
+          return builder.toString();
+        }
+      }
+
+      if (value instanceof Collection)
+      {
+        StringBuilder builder = new StringBuilder();
+        for (Object element : (Collection<?>)value)
+        {
+          builder.append(builder.length() == 0 ? "" : "<br>");
+          builder.append(getRevisionValue(element, browser, ids, context));
+        }
+
+        return builder.toString();
+      }
+
+      return value;
+    }
+
+    private String getVersionPrefix(CDORevision revision)
+    {
+      if (revision instanceof PointerCDORevision)
+      {
+        return "p";
+      }
+
+      if (revision instanceof DetachedCDORevision)
+      {
+        return "d";
+      }
+
+      return "v";
+    }
+
+    /**
+     * @since 4.0
+     */
+    protected void showKeyValue(PrintStream pout, boolean bg, String key, Object value)
+    {
+      String color = bg ? "EEEEEE" : "FFFFFF";
+      pout.print("<tr bgcolor=\"" + color + "\">\r\n");
+      pout.print("<td valign=\"top\"><b>" + key + "</b></td>\r\n");
+      pout.print("<td valign=\"top\">");
+      pout.print(value);
+      pout.print("</td>\r\n");
+      pout.print("</tr>\r\n");
+    }
+
+    protected abstract Map<CDOBranch, List<CDORevision>> getAllRevisions(InternalRepository repository);
+
+    private Map<CDOID, List<CDORevision>> getAllIDs(Map<CDOBranch, List<CDORevision>> allRevisions)
+    {
+      Map<CDOID, List<CDORevision>> ids = new HashMap<CDOID, List<CDORevision>>();
+      for (List<CDORevision> list : allRevisions.values())
+      {
+        for (CDORevision revision : list)
+        {
+          CDOID id = revision.getID();
+          List<CDORevision> revisions = ids.get(id);
+          if (revisions == null)
+          {
+            revisions = new ArrayList<CDORevision>();
+            ids.put(id, revisions);
+          }
+
+          revisions.add(revision);
+        }
+      }
+
+      return ids;
+    }
+
+    protected String getCDOIDLabel(CDORevision revision)
+    {
+      String label = revision.toString();
+      return label.substring(0, label.indexOf(':'));
+    }
+
+    /**
+     * @author Eike Stepper
+     */
+    public static class FromCache extends RevisionsPage
+    {
+      public static final String NAME = "crevisions";
+
+      public FromCache()
+      {
+        super(NAME, "Revisions From Cache");
+      }
+
+      public boolean canDisplay(InternalRepository repository)
+      {
+        return true;
+      }
+
+      @Override
+      protected Map<CDOBranch, List<CDORevision>> getAllRevisions(InternalRepository repository)
+      {
+        return repository.getRevisionManager().getCache().getAllRevisions();
+      }
+    }
+
+    /**
+     * @author Eike Stepper
+     */
+    public static class FromStore extends RevisionsPage
+    {
+      public static final String NAME = "srevisions";
+
+      public FromStore()
+      {
+        super(NAME, "Revisions From Store");
+      }
+
+      public boolean canDisplay(InternalRepository repository)
+      {
+        return repository.getStore() instanceof CDOAllRevisionsProvider;
+      }
+
+      @Override
+      protected Map<CDOBranch, List<CDORevision>> getAllRevisions(InternalRepository repository)
+      {
+        return ((CDOAllRevisionsProvider)repository.getStore()).getAllRevisions();
+      }
+    }
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  public static class LobsPage extends AbstractPage
+  {
+    public static final String NAME = "lobs";
+
+    public LobsPage()
+    {
+      super(NAME, "Large Objects");
+    }
+
+    public boolean canDisplay(InternalRepository repository)
+    {
+      return true;
+    }
+
+    public void display(final CDOServerBrowser browser, InternalRepository repository, final PrintStream out)
+    {
+      out.print("<table border=\"0\">\r\n");
+      out.print("<tr>\r\n");
+      out.print("<td valign=\"top\">\r\n");
+
+      IStoreAccessor accessor = repository.getStore().getReader(null);
+      StoreThreadLocal.setAccessor(accessor);
+
+      final String param = browser.getParam("id");
+      final Object[] details = { null, null, null };
+
+      try
+      {
+        repository.handleLobs(0, 0, new CDOLobHandler()
+        {
+          public OutputStream handleBlob(byte[] id, long size)
+          {
+            if (showLob(out, "Blob", id, size, browser, param))
+            {
+              ByteArrayOutputStream result = new ByteArrayOutputStream();
+              details[0] = result;
+              details[1] = param;
+              details[2] = size;
+              return result;
+            }
+
+            return null;
+          }
+
+          public Writer handleClob(byte[] id, long size)
+          {
+            if (showLob(out, "Clob", id, size, browser, param))
+            {
+              CharArrayWriter result = new CharArrayWriter();
+              details[0] = result;
+              details[1] = param;
+              details[2] = size;
+              return result;
+            }
+
+            return null;
+          }
+        });
+      }
+      catch (IOException ex)
+      {
+        throw WrappedException.wrap(ex);
+      }
+      finally
+      {
+        StoreThreadLocal.release();
+      }
+
+      out.print("</td>\r\n");
+
+      if (details[0] != null)
+      {
+        out.print("<td>&nbsp;&nbsp;&nbsp;</td>\r\n");
+        out.print("<td valign=\"top\">\r\n");
+        if (details[0] instanceof ByteArrayOutputStream)
+        {
+          ByteArrayOutputStream baos = (ByteArrayOutputStream)details[0];
+          String hex = HexUtil.bytesToHex(baos.toByteArray());
+
+          out.println("<h3>Blob " + details[1] + " (" + details[2] + ")</h3>");
+          out.println("<pre>\r\n");
+          for (int i = 0; i < hex.length(); i++)
+          {
+            out.print(hex.charAt(i));
+            if ((i + 1) % 32 == 0)
+            {
+              out.print("\r\n");
+            }
+            else if ((i + 1) % 16 == 0)
+            {
+              out.print("  ");
+            }
+            else if ((i + 1) % 2 == 0)
+            {
+              out.print(" ");
+            }
+          }
+
+          out.println("</pre>\r\n");
+        }
+        else
+        {
+          CharArrayWriter caw = (CharArrayWriter)details[0];
+          out.println("<h3>Clob " + details[1] + " (" + details[2] + ")</h3>");
+          out.println("<pre>" + caw + "</pre>");
+        }
+
+        out.print("</td>\r\n");
+      }
+
+      out.print("</tr>\r\n");
+      out.print("</table>\r\n");
+    }
+
+    protected boolean showLob(PrintStream out, String type, byte[] id, long size, CDOServerBrowser browser, String param)
+    {
+      String hex = HexUtil.bytesToHex(id);
+      boolean selected = hex.equals(param);
+      String label = selected ? hex : browser.href(hex, getName(), "id", hex);
+      out.println(type + " " + label + " (" + size + ")");
+      return selected;
+    }
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  public static class HistoryPage extends AbstractPage
+  {
+    public static final String NAME = "history";
+
+    public HistoryPage()
+    {
+      super(NAME, "Commit Infos");
+    }
+
+    public boolean canDisplay(InternalRepository repository)
+    {
+      return true;
+    }
+
+    public void display(final CDOServerBrowser browser, InternalRepository repository, final PrintStream out)
+    {
+      out.print("<table border=\"0\">\r\n");
+      out.print("<tr>\r\n");
+      out.print("<td valign=\"top\">\r\n");
+
+      IStoreAccessor accessor = repository.getStore().getReader(null);
+      StoreThreadLocal.setAccessor(accessor);
+
+      final String param = browser.getParam("time");
+
+      out.print("<table border=\"1\" cellpadding=\"2\">\r\n");
+      out.print("<tr>\r\n");
+      out.print("<td valign=\"top\">Time</td>\r\n");
+      out.print("<td valign=\"top\">Branch</td>\r\n");
+      out.print("<td valign=\"top\">User</td>\r\n");
+      out.print("<td valign=\"top\">Comment</td>\r\n");
+      out.print("</tr>\r\n");
+
+      final CDOCommitInfo[] details = { null };
+
+      try
+      {
+        final boolean auditing = repository.isSupportingAudits();
+        repository.getCommitInfoManager().getCommitInfos(null, 0L, 0L, new CDOCommitInfoHandler()
+        {
+          public void handleCommitInfo(CDOCommitInfo commitInfo)
+          {
+            if (showCommitInfo(out, commitInfo, browser, param, auditing))
+            {
+              details[0] = commitInfo;
+            }
+          }
+        });
+
+        out.print("</table>\r\n");
+        out.print("</td>\r\n");
+        out.print("<td>&nbsp;&nbsp;&nbsp;</td>\r\n");
+        out.print("<td valign=\"top\">\r\n");
+
+        if (auditing)
+        {
+          CDOCommitInfo commitInfo = details[0];
+          if (commitInfo != null)
+          {
+            out.print("<h3>Commit Info " + commitInfo.getTimeStamp() + "</h3>\r\n");
+            showCommitData(out, commitInfo, browser);
+          }
+        }
+        else
+        {
+          out.print("<h3>No audit data available in this repository.</h3>\r\n");
+        }
+
+        out.print("</td>\r\n");
+        out.print("</tr>\r\n");
+        out.print("</table>\r\n");
+      }
+      finally
+      {
+        StoreThreadLocal.release();
+      }
+    }
+
+    protected boolean showCommitInfo(PrintStream out, CDOCommitInfo commitInfo, CDOServerBrowser browser, String param,
+        boolean auditing)
+    {
+      String timeStamp = String.valueOf(commitInfo.getTimeStamp());
+      boolean selected = timeStamp.equals(param);
+
+      String formatted = CDOCommonUtil.formatTimeStamp(commitInfo.getTimeStamp()).replaceAll(" ", "&nbsp;");
+      String label = formatted;
+      if (!selected && auditing)
+      {
+        label = browser.href(formatted, getName(), "time", timeStamp);
+      }
+
+      out.print("<tr>\r\n");
+      out.print("<td valign=\"top\">\r\n");
+      out.print(label);
+      out.print("</td>\r\n");
+
+      CDOBranch branch = commitInfo.getBranch();
+      out.print("<td valign=\"top\">\r\n");
+      out.print(branch.getName() + "[" + branch.getID() + "]");
+      out.print("</td>\r\n");
+
+      String userID = commitInfo.getUserID();
+      out.print("<td valign=\"top\">\r\n");
+      out.print(StringUtil.isEmpty(userID) ? "&nbsp;" : browser.escape(userID));
+      out.print("</td>\r\n");
+
+      String comment = commitInfo.getComment();
+      out.print("<td valign=\"top\">\r\n");
+      out.print(StringUtil.isEmpty(comment) ? "&nbsp;" : browser.escape(comment));
+      out.print("</td>\r\n");
+
+      out.print("</tr>\r\n");
+      return selected;
+    }
+
+    protected void showCommitData(PrintStream out, CDOCommitInfo commitInfo, CDOServerBrowser browser)
+    {
+      out.print("<h4>New Objects:</h4>\r\n");
+      out.print("<ul>\r\n");
+      for (CDOIDAndVersion key : commitInfo.getNewObjects())
+      {
+        CDORevision newObject = (CDORevision)key;
+        out.print("<li>"
+            + browser.href(newObject.toString(), RevisionsPage.FromStore.NAME, "revision",
+                CDORevisionUtil.formatRevisionKey(newObject)) + "<br>\r\n");
+      }
+
+      out.print("</ul>\r\n");
+      out.print("<h4>Changed Objects:</h4>\r\n");
+      out.print("<ul>\r\n");
+      for (CDORevisionKey key : commitInfo.getChangedObjects())
+      {
+        CDORevisionDelta changedObject = (CDORevisionDelta)key;
+        out.print("<li>" + changedObject.toString() + "<br>\r\n");
+      }
+
+      out.print("</ul>\r\n");
+      out.print("<h4>Detached Objects:</h4>\r\n");
+      out.print("<ul>\r\n");
+      for (CDOIDAndVersion key : commitInfo.getDetachedObjects())
+      {
+        out.print("<li>" + key.toString() + "<br>\r\n");
+      }
+
+      out.print("</ul>\r\n");
+    }
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/CDOServerExporter.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/CDOServerExporter.java
new file mode 100644
index 0000000..cc9a2ad
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/CDOServerExporter.java
@@ -0,0 +1,695 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchHandler;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
+import org.eclipse.emf.cdo.common.commit.CDOCommitInfoHandler;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.id.CDOIDUtil;
+import org.eclipse.emf.cdo.common.lob.CDOBlob;
+import org.eclipse.emf.cdo.common.lob.CDOClob;
+import org.eclipse.emf.cdo.common.lob.CDOLobHandler;
+import org.eclipse.emf.cdo.common.model.CDOClassInfo;
+import org.eclipse.emf.cdo.common.model.CDOClassifierRef;
+import org.eclipse.emf.cdo.common.model.CDOPackageUnit;
+import org.eclipse.emf.cdo.common.model.EMFUtil;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionHandler;
+import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranchManager;
+import org.eclipse.emf.cdo.spi.common.commit.InternalCDOCommitInfoManager;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageInfo;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+import org.eclipse.emf.cdo.spi.server.InternalRepository;
+import org.eclipse.emf.cdo.spi.server.InternalSession;
+
+import org.eclipse.net4j.util.HexUtil;
+import org.eclipse.net4j.util.WrappedException;
+import org.eclipse.net4j.util.io.XMLOutput;
+import org.eclipse.net4j.util.lifecycle.LifecycleUtil;
+
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.util.FeatureMap;
+import org.eclipse.emf.ecore.util.FeatureMapUtil;
+
+import org.xml.sax.SAXException;
+
+import java.io.OutputStream;
+import java.io.Writer;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @author Eike Stepper
+ * @since 4.0
+ */
+public abstract class CDOServerExporter<OUT>
+{
+  private InternalRepository repository;
+
+  public CDOServerExporter(IRepository repository)
+  {
+    this.repository = (InternalRepository)repository;
+  }
+
+  public final IRepository getRepository()
+  {
+    return repository;
+  }
+
+  public final void exportRepository(OutputStream out) throws Exception
+  {
+    boolean wasActive = LifecycleUtil.isActive(repository);
+    if (!wasActive)
+    {
+      LifecycleUtil.activate(repository);
+    }
+
+    InternalSession session = repository.getSessionManager().openSession(null);
+    StoreThreadLocal.setSession(session);
+
+    try
+    {
+      OUT output = createOutput(out);
+      exportAll(output);
+    }
+    finally
+    {
+      StoreThreadLocal.release();
+      if (!wasActive)
+      {
+        LifecycleUtil.deactivate(repository);
+      }
+
+      repository = null;
+    }
+  }
+
+  protected abstract OUT createOutput(OutputStream out) throws Exception;
+
+  protected void exportAll(final OUT out) throws Exception
+  {
+    try
+    {
+      exportPackages(out);
+      exportBranches(out);
+      exportLobs(out);
+      exportCommits(out);
+    }
+    catch (WrappedException ex)
+    {
+      throw WrappedException.unwrap(ex);
+    }
+  }
+
+  protected void exportPackages(OUT out) throws Exception
+  {
+    InternalCDOPackageRegistry packageRegistry = repository.getPackageRegistry(false);
+    InternalCDOPackageUnit[] packageUnits = packageRegistry.getPackageUnits(false);
+    for (InternalCDOPackageUnit packageUnit : packageUnits)
+    {
+      String id = packageUnit.getID();
+      CDOPackageUnit.Type type = packageUnit.getOriginalType();
+      long time = packageUnit.getTimeStamp();
+
+      EPackage ePackage = packageUnit.getTopLevelPackageInfo().getEPackage();
+      String data = new String(EMFUtil.getEPackageBytes(ePackage, false, packageRegistry));
+
+      startPackageUnit(out, id, type, time, data);
+      for (InternalCDOPackageInfo packageInfo : packageUnit.getPackageInfos())
+      {
+        String packageURI = packageInfo.getPackageURI();
+        exportPackageInfo(out, packageURI);
+      }
+
+      endPackageUnit(out);
+    }
+  }
+
+  protected abstract void startPackageUnit(OUT out, String id, CDOPackageUnit.Type type, long time, String data)
+      throws Exception;
+
+  protected abstract void endPackageUnit(OUT out) throws Exception;
+
+  protected abstract void exportPackageInfo(OUT out, String packageURI) throws Exception;
+
+  protected void exportBranches(final OUT out) throws Exception
+  {
+    InternalCDOBranchManager branchManager = repository.getBranchManager();
+    exportBranch(out, branchManager.getMainBranch());
+
+    if (repository.isSupportingBranches())
+    {
+      branchManager.getBranches(0, 0, new CDOBranchHandler()
+      {
+        public void handleBranch(CDOBranch branch)
+        {
+          try
+          {
+            exportBranch(out, branch);
+          }
+          catch (Exception ex)
+          {
+            throw WrappedException.wrap(ex);
+          }
+        }
+      });
+    }
+  }
+
+  protected void exportBranch(OUT out, CDOBranch branch) throws Exception
+  {
+    exportRevisions(out, branch);
+  }
+
+  protected void exportRevisions(final OUT out, CDOBranch branch) throws Exception
+  {
+    repository.handleRevisions(null, branch, true, CDOBranchPoint.INVALID_DATE, false,
+        new CDORevisionHandler.Filtered.Undetached(new CDORevisionHandler()
+        {
+          public boolean handleRevision(CDORevision revision)
+          {
+            try
+            {
+              exportRevision(out, revision);
+              return true;
+            }
+            catch (Exception ex)
+            {
+              throw WrappedException.wrap(ex);
+            }
+          }
+        }));
+  }
+
+  protected abstract void exportRevision(OUT out, CDORevision revision) throws Exception;
+
+  protected void exportLobs(final OUT out) throws Exception
+  {
+    repository.handleLobs(0, 0, new CDOLobHandler()
+    {
+      public OutputStream handleBlob(byte[] id, long size)
+      {
+        try
+        {
+          return startBlob(out, id, size);
+        }
+        catch (Exception ex)
+        {
+          throw WrappedException.wrap(ex);
+        }
+      }
+
+      public Writer handleClob(byte[] id, long size)
+      {
+        try
+        {
+          return startClob(out, id, size);
+        }
+        catch (Exception ex)
+        {
+          throw WrappedException.wrap(ex);
+        }
+      }
+    });
+  }
+
+  protected abstract OutputStream startBlob(OUT out, byte[] id, long size) throws Exception;
+
+  protected abstract Writer startClob(OUT out, byte[] id, long size) throws Exception;
+
+  protected void exportCommits(final OUT out) throws Exception
+  {
+    InternalCDOCommitInfoManager commitInfoManager = repository.getCommitInfoManager();
+    commitInfoManager.getCommitInfos(null, 0L, 0L, new CDOCommitInfoHandler()
+    {
+      public void handleCommitInfo(CDOCommitInfo commitInfo)
+      {
+        try
+        {
+          exportCommit(out, commitInfo);
+        }
+        catch (Exception ex)
+        {
+          throw WrappedException.wrap(ex);
+        }
+      }
+    });
+  }
+
+  protected abstract void exportCommit(OUT out, CDOCommitInfo commitInfo) throws Exception;
+
+  /**
+   * @author Eike Stepper
+   */
+  public static interface XMLConstants
+  {
+    public static final String REPOSITORY = "repository";
+
+    public static final String REPOSITORY_NAME = "name";
+
+    public static final String REPOSITORY_UUID = "uuid";
+
+    public static final String REPOSITORY_ROOT = "root";
+
+    public static final String REPOSITORY_CREATED = "created";
+
+    public static final String REPOSITORY_COMMITTED = "committed";
+
+    public static final String MODELS = "models";
+
+    public static final String PACKAGE_UNIT = "packageUnit";
+
+    public static final String PACKAGE_UNIT_ID = "id";
+
+    public static final String PACKAGE_UNIT_TYPE = "type";
+
+    public static final String PACKAGE_UNIT_TIME = "time";
+
+    public static final String PACKAGE_UNIT_DATA = "data";
+
+    public static final String PACKAGE_INFO = "packageInfo";
+
+    public static final String PACKAGE_INFO_URI = "uri";
+
+    public static final String INSTANCES = "instances";
+
+    public static final String BRANCH = "branch";
+
+    public static final String BRANCH_ID = "id";
+
+    public static final String BRANCH_NAME = "name";
+
+    public static final String BRANCH_TIME = "time";
+
+    public static final String BRANCH_PARENT = "parent";
+
+    public static final String REVISION = "revision";
+
+    public static final String REVISION_ID = "id";
+
+    public static final String REVISION_CLASS = "class";
+
+    public static final String REVISION_VERSION = "version";
+
+    public static final String REVISION_TIME = "time";
+
+    public static final String REVISION_REVISED = "revised";
+
+    public static final String REVISION_RESOURCE = "resource";
+
+    public static final String REVISION_CONTAINER = "container";
+
+    public static final String REVISION_FEATURE = "feature";
+
+    public static final String FEATURE = "feature";
+
+    public static final String FEATURE_NAME = "name";
+
+    public static final String FEATURE_TYPE = "type";
+
+    public static final String FEATURE_INNER_FEATURE = "innerFeature";
+
+    public static final String FEATURE_INNER_TYPE = "innerType";
+
+    public static final String FEATURE_VALUE = "value";
+
+    public static final String FEATURE_ID = "id";
+
+    public static final String FEATURE_SIZE = "size";
+
+    public static final String TYPE_BLOB = "Blob";
+
+    public static final String TYPE_CLOB = "Clob";
+
+    public static final String TYPE_FEATURE_MAP = "FeatureMap";
+
+    public static final String LOBS = "lobs";
+
+    public static final String LOB_ID = "id";
+
+    public static final String LOB_SIZE = "size";
+
+    public static final String BLOB = "blob";
+
+    public static final String CLOB = "clob";
+
+    public static final String COMMITS = "commits";
+
+    public static final String COMMIT = "commit";
+
+    public static final String COMMIT_TIME = "time";
+
+    public static final String COMMIT_PREVIOUS = "previous";
+
+    public static final String COMMIT_BRANCH = "branch";
+
+    public static final String COMMIT_USER = "user";
+
+    public static final String COMMIT_COMMENT = "comment";
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  public static class XML extends CDOServerExporter<XMLOutput> implements XMLConstants
+  {
+    public XML(IRepository repository)
+    {
+      super(repository);
+    }
+
+    @Override
+    protected final XMLOutput createOutput(OutputStream out) throws Exception
+    {
+      return new XMLOutput(out);
+    }
+
+    @Override
+    protected void exportAll(XMLOutput out) throws Exception
+    {
+      out.element(REPOSITORY);
+      out.attribute(REPOSITORY_NAME, getRepository().getName());
+      out.attribute(REPOSITORY_UUID, getRepository().getUUID());
+      out.attribute(REPOSITORY_ROOT, str(getRepository().getRootResourceID()));
+      out.attribute(REPOSITORY_CREATED, getRepository().getStore().getCreationTime());
+      out.attribute(REPOSITORY_COMMITTED, getRepository().getLastCommitTimeStamp());
+
+      out.push();
+      super.exportAll(out);
+      out.done();
+    }
+
+    @Override
+    protected void exportPackages(XMLOutput out) throws Exception
+    {
+      out.element(MODELS);
+
+      out.push();
+      super.exportPackages(out);
+      out.pop();
+    }
+
+    @Override
+    protected void startPackageUnit(XMLOutput out, String id, CDOPackageUnit.Type type, long time, String data)
+        throws Exception
+    {
+      out.element(PACKAGE_UNIT);
+      out.attribute(PACKAGE_UNIT_ID, id);
+      out.attribute(PACKAGE_UNIT_TYPE, type);
+      out.attribute(PACKAGE_UNIT_TIME, time);
+      out.attribute(PACKAGE_UNIT_DATA, data);
+      out.push();
+    }
+
+    @Override
+    protected void endPackageUnit(XMLOutput out) throws Exception
+    {
+      out.pop();
+    }
+
+    @Override
+    protected void exportPackageInfo(XMLOutput out, String uri) throws Exception
+    {
+      out.element(PACKAGE_INFO);
+      out.attribute(PACKAGE_INFO_URI, uri);
+    }
+
+    @Override
+    protected void exportBranches(XMLOutput out) throws Exception
+    {
+      out.element(INSTANCES);
+
+      out.push();
+      super.exportBranches(out);
+      out.pop();
+    }
+
+    @Override
+    protected void exportBranch(XMLOutput out, CDOBranch branch) throws Exception
+    {
+      out.element(BRANCH);
+      out.attribute(BRANCH_ID, branch.getID());
+      out.attribute(BRANCH_NAME, branch.getName());
+      out.attribute(BRANCH_TIME, branch.getBase().getTimeStamp());
+      if (!branch.isMainBranch())
+      {
+        out.attribute(BRANCH_PARENT, branch.getBase().getBranch().getID());
+      }
+
+      out.push();
+      super.exportBranch(out, branch);
+      out.pop();
+
+    }
+
+    @Override
+    protected void exportRevision(XMLOutput out, CDORevision revision) throws Exception
+    {
+      InternalCDORevision rev = (InternalCDORevision)revision;
+
+      out.element(REVISION);
+      out.attribute(REVISION_ID, str(rev.getID()));
+      out.attribute(REVISION_CLASS, new CDOClassifierRef(rev.getEClass()).getURI());
+      out.attribute(REVISION_VERSION, rev.getVersion());
+      out.attribute(REVISION_TIME, rev.getTimeStamp());
+
+      long revised = rev.getRevised();
+      if (revised != CDOBranchPoint.UNSPECIFIED_DATE)
+      {
+        out.attribute(REVISION_REVISED, revised);
+      }
+
+      CDOID resourceID = rev.getResourceID();
+      if (!CDOIDUtil.isNull(resourceID))
+      {
+        out.attribute(REVISION_RESOURCE, str(resourceID));
+      }
+
+      CDOID containerID = (CDOID)rev.getContainerID();
+      if (!CDOIDUtil.isNull(containerID))
+      {
+        out.attribute(REVISION_CONTAINER, str(containerID));
+      }
+
+      int containingFeatureID = rev.getContainingFeatureID();
+      if (containingFeatureID != 0)
+      {
+        out.attribute(REVISION_FEATURE, containingFeatureID);
+      }
+
+      out.push();
+      CDOClassInfo classInfo = rev.getClassInfo();
+      for (EStructuralFeature feature : classInfo.getAllPersistentFeatures())
+      {
+        if (feature.isMany())
+        {
+          @SuppressWarnings("unchecked")
+          List<Object> list = (List<Object>)rev.getValue(feature);
+          if (list != null)
+          {
+            for (Object value : list)
+            {
+              exportFeature(out, feature, value);
+            }
+          }
+        }
+        else
+        {
+          Object value = rev.getValue(feature);
+          if (value != null)
+          {
+            exportFeature(out, feature, value);
+          }
+        }
+      }
+
+      out.pop();
+    }
+
+    protected void exportFeature(XMLOutput out, EStructuralFeature feature, Object value) throws Exception
+    {
+      out.element(FEATURE);
+      out.attribute(FEATURE_NAME, feature.getName());
+      exportFeature(out, feature, FEATURE_TYPE, value);
+    }
+
+    protected void exportFeature(XMLOutput out, EStructuralFeature feature, String featureType, Object value)
+        throws SAXException
+    {
+      if (value instanceof CDOID)
+      {
+        out.attribute(featureType, Object.class.getSimpleName());
+        out.attribute(FEATURE_VALUE, str((CDOID)value));
+      }
+      else if (value instanceof CDOBlob)
+      {
+        CDOBlob blob = (CDOBlob)value;
+        out.attribute(featureType, TYPE_BLOB);
+        out.attribute(FEATURE_ID, HexUtil.bytesToHex(blob.getID()));
+        out.attribute(FEATURE_SIZE, blob.getSize());
+      }
+      else if (value instanceof CDOClob)
+      {
+        CDOClob clob = (CDOClob)value;
+        out.attribute(featureType, TYPE_CLOB);
+        out.attribute(FEATURE_ID, HexUtil.bytesToHex(clob.getID()));
+        out.attribute(FEATURE_SIZE, clob.getSize());
+      }
+      else if (value instanceof Date)
+      {
+        Date date = (Date)value;
+        out.attribute(featureType, Date.class.getSimpleName());
+        out.attribute(FEATURE_VALUE, date.getTime());
+      }
+      else if (FeatureMapUtil.isFeatureMap(feature))
+      {
+        FeatureMap.Entry entry = (FeatureMap.Entry)value;
+        EStructuralFeature innerFeature = entry.getEStructuralFeature();
+        Object innerValue = entry.getValue();
+
+        out.attribute(featureType, TYPE_FEATURE_MAP);
+        out.attribute(FEATURE_INNER_FEATURE, innerFeature.getName());
+        exportFeature(out, innerFeature, FEATURE_INNER_TYPE, innerValue);
+      }
+      else
+      {
+        if (!(value instanceof String))
+        {
+          out.attribute(featureType, type(value));
+        }
+
+        out.attributeOrNull(FEATURE_VALUE, value);
+      }
+    }
+
+    @Override
+    protected void exportLobs(XMLOutput out) throws Exception
+    {
+      out.element(LOBS);
+
+      out.push();
+      super.exportLobs(out);
+      out.pop();
+    }
+
+    @Override
+    protected OutputStream startBlob(XMLOutput out, byte[] id, long size) throws Exception
+    {
+      out.element(BLOB);
+      out.attribute(LOB_ID, HexUtil.bytesToHex(id));
+      out.attribute(LOB_SIZE, size);
+      return out.bytes();
+    }
+
+    @Override
+    protected Writer startClob(XMLOutput out, byte[] id, long size) throws Exception
+    {
+      out.element(CLOB);
+      out.attribute(LOB_ID, HexUtil.bytesToHex(id));
+      out.attribute(LOB_SIZE, size);
+      return out.characters();
+    }
+
+    @Override
+    protected void exportCommits(XMLOutput out) throws Exception
+    {
+      out.element(COMMITS);
+
+      out.push();
+      super.exportCommits(out);
+      out.pop();
+    }
+
+    @Override
+    protected void exportCommit(XMLOutput out, CDOCommitInfo commitInfo) throws Exception
+    {
+      out.element(COMMIT);
+      out.attribute(COMMIT_TIME, commitInfo.getTimeStamp());
+      long previous = commitInfo.getPreviousTimeStamp();
+      if (previous != CDOBranchPoint.UNSPECIFIED_DATE)
+      {
+        out.attribute(COMMIT_PREVIOUS, previous);
+      }
+
+      int branch = commitInfo.getBranch().getID();
+      if (branch != CDOBranch.MAIN_BRANCH_ID)
+      {
+        out.attribute(COMMIT_BRANCH, branch);
+      }
+
+      out.attribute(COMMIT_USER, commitInfo.getUserID());
+      out.attribute(COMMIT_COMMENT, commitInfo.getComment());
+    }
+
+    protected final String str(CDOID id)
+    {
+      StringBuilder builder = new StringBuilder();
+      CDOIDUtil.write(builder, id);
+      return builder.toString();
+    }
+
+    protected String type(Object value)
+    {
+      if (value instanceof Boolean)
+      {
+        return Boolean.class.getSimpleName();
+      }
+
+      if (value instanceof Character)
+      {
+        return Character.class.getSimpleName();
+      }
+
+      if (value instanceof Byte)
+      {
+        return Byte.class.getSimpleName();
+      }
+
+      if (value instanceof Short)
+      {
+        return Short.class.getSimpleName();
+      }
+
+      if (value instanceof Integer)
+      {
+        return Integer.class.getSimpleName();
+      }
+
+      if (value instanceof Long)
+      {
+        return Long.class.getSimpleName();
+      }
+
+      if (value instanceof Float)
+      {
+        return Float.class.getSimpleName();
+      }
+
+      if (value instanceof Double)
+      {
+        return Double.class.getSimpleName();
+      }
+
+      if (value instanceof String)
+      {
+        return String.class.getSimpleName();
+      }
+
+      throw new IllegalArgumentException("Invalid type: " + value.getClass().getName());
+    }
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/CDOServerImporter.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/CDOServerImporter.java
new file mode 100644
index 0000000..2441d71
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/CDOServerImporter.java
@@ -0,0 +1,663 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.id.CDOIDUtil;
+import org.eclipse.emf.cdo.common.lob.CDOLobHandler;
+import org.eclipse.emf.cdo.common.lob.CDOLobUtil;
+import org.eclipse.emf.cdo.common.model.CDOClassifierRef;
+import org.eclipse.emf.cdo.common.model.CDOModelUtil;
+import org.eclipse.emf.cdo.common.model.CDOPackageUnit;
+import org.eclipse.emf.cdo.common.model.CDOPackageUnit.Type;
+import org.eclipse.emf.cdo.common.model.EMFUtil;
+import org.eclipse.emf.cdo.common.model.EMFUtil.ExtResourceSet;
+import org.eclipse.emf.cdo.common.revision.CDOList;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionFactory;
+import org.eclipse.emf.cdo.common.revision.CDORevisionHandler;
+import org.eclipse.emf.cdo.common.revision.CDORevisionUtil;
+import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranch;
+import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranchManager;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageInfo;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry.PackageLoader;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+import org.eclipse.emf.cdo.spi.server.InternalRepository;
+
+import org.eclipse.net4j.util.HexUtil;
+import org.eclipse.net4j.util.WrappedException;
+import org.eclipse.net4j.util.io.AsyncOutputStream;
+import org.eclipse.net4j.util.io.AsyncWriter;
+import org.eclipse.net4j.util.io.IOUtil;
+import org.eclipse.net4j.util.lifecycle.LifecycleUtil;
+import org.eclipse.net4j.util.om.monitor.Monitor;
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Eike Stepper
+ * @since 4.0
+ * @apiviz.has {@link CDOServerImporter.Handler}
+ */
+public abstract class CDOServerImporter
+{
+  private InternalRepository repository;
+
+  public CDOServerImporter(IRepository repository)
+  {
+    this.repository = (InternalRepository)repository;
+    init();
+  }
+
+  private void init()
+  {
+    LifecycleUtil.checkInactive(repository);
+    repository.setSkipInitialization(true);
+    repository.getStore().setDropAllDataOnActivate(true);
+    LifecycleUtil.activate(repository);
+  }
+
+  protected final InternalRepository getRepository()
+  {
+    return repository;
+  }
+
+  public void importRepository(InputStream in) throws Exception
+  {
+    try
+    {
+      FlushHandler handler = new FlushHandler();
+      importAll(in, handler);
+      handler.flush();
+    }
+    finally
+    {
+      StoreThreadLocal.release();
+      repository = null;
+    }
+  }
+
+  protected abstract void importAll(InputStream in, Handler handler) throws Exception;
+
+  /**
+   * @author Eike Stepper
+   */
+  public static interface Handler extends CDORevisionHandler, CDOLobHandler
+  {
+    public void handleRepository(String name, String uuid, CDOID root, long created, long committed);
+
+    public InternalCDOPackageUnit handlePackageUnit(String id, Type type, long time, String data);
+
+    public InternalCDOPackageInfo handlePackageInfo(String packageURI);
+
+    public InternalCDOPackageRegistry handleModels();
+
+    public InternalCDOBranch handleBranch(int id, String name, long time, int parentID);
+
+    public void handleCommitInfo(long time, long previous, int branch, String user, String comment);
+
+    public void flush();
+
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  private final class FlushHandler implements Handler
+  {
+    private OMMonitor monitor = new Monitor();
+
+    private IStoreAccessor.Raw accessor;
+
+    private Map<String, String> models = new HashMap<String, String>();
+
+    private LinkedList<InternalCDOPackageUnit> packageUnits = new LinkedList<InternalCDOPackageUnit>();
+
+    private List<InternalCDOPackageInfo> packageInfos;
+
+    private InternalCDOPackageRegistry packageRegistry = getRepository().getPackageRegistry(false);
+
+    public FlushHandler()
+    {
+    }
+
+    public void handleRepository(String name, String uuid, CDOID root, long created, long committed)
+    {
+      repository.getStore().setCreationTime(created);
+      repository.getStore().setLastCommitTime(committed);
+
+      InternalCDOBranchManager branchManager = repository.getBranchManager();
+      repository.initMainBranch(branchManager, created);
+      LifecycleUtil.activate(branchManager);
+
+      repository.initSystemPackages();
+      repository.setRootResourceID(root);
+
+      // InternalSession session = repository.getSessionManager().openSession(null);
+      // StoreThreadLocal.setSession(session);
+
+      accessor = (IStoreAccessor.Raw)repository.getStore().getWriter(null);
+      StoreThreadLocal.setAccessor(accessor);
+    }
+
+    public InternalCDOPackageUnit handlePackageUnit(String id, Type type, long time, String data)
+    {
+      collectPackageInfos();
+
+      InternalCDOPackageUnit packageUnit = packageRegistry.createPackageUnit();
+      packageUnit.setOriginalType(type);
+      packageUnit.setTimeStamp(time);
+
+      models.put(id, data);
+      packageUnits.add(packageUnit);
+      packageInfos = new ArrayList<InternalCDOPackageInfo>();
+      return packageUnit;
+    }
+
+    public InternalCDOPackageInfo handlePackageInfo(String packageURI)
+    {
+      InternalCDOPackageInfo packageInfo = (InternalCDOPackageInfo)CDOModelUtil.createPackageInfo();
+      packageInfo.setPackageURI(packageURI);
+      packageInfos.add(packageInfo);
+      return packageInfo;
+    }
+
+    public InternalCDOPackageRegistry handleModels()
+    {
+      collectPackageInfos();
+      InternalCDOPackageUnit[] array = packageUnits.toArray(new InternalCDOPackageUnit[packageUnits.size()]);
+      packageUnits = null;
+
+      final ExtResourceSet resourceSet = EMFUtil.createExtResourceSet(packageRegistry, false, false);
+
+      PackageLoader loader = new PackageLoader()
+      {
+        public EPackage[] loadPackages(CDOPackageUnit packageUnit)
+        {
+          String id = packageUnit.getID();
+          String data = models.get(id);
+
+          EPackage ePackage = EMFUtil.createEPackage(id, data.getBytes(), false, resourceSet, true);
+          return EMFUtil.getAllPackages(ePackage);
+        }
+      };
+
+      packageRegistry.putPackageUnits(array, CDOPackageUnit.State.PROXY);
+      for (InternalCDOPackageUnit packageUnit : array)
+      {
+        packageUnit.load(loader, false);
+      }
+
+      // Before we resolve, we configure the resourceSet to start delegating, which means
+      // it will consult the packageRegistry for packages it didn't just load -- such as the Ecore
+      // package
+      resourceSet.setDelegating(true);
+      EMFUtil.safeResolveAll(resourceSet);
+
+      accessor.rawStore(array, monitor);
+
+      return packageRegistry;
+    }
+
+    public InternalCDOBranch handleBranch(int id, String name, long time, int parentID)
+    {
+      InternalCDOBranchManager branchManager = repository.getBranchManager();
+      if (id == CDOBranch.MAIN_BRANCH_ID)
+      {
+        return branchManager.getMainBranch();
+      }
+
+      InternalCDOBranch parent = branchManager.getBranch(parentID);
+      return branchManager.createBranch(id, name, parent, time);
+    }
+
+    public boolean handleRevision(CDORevision revision)
+    {
+      accessor.rawStore((InternalCDORevision)revision, monitor);
+      return true;
+    }
+
+    public OutputStream handleBlob(final byte[] id, final long size) throws IOException
+    {
+      return new AsyncOutputStream()
+      {
+        @Override
+        protected void asyncWrite(InputStream in) throws IOException
+        {
+          accessor.rawStore(id, size, in);
+        }
+      };
+    }
+
+    public Writer handleClob(final byte[] id, final long size) throws IOException
+    {
+      return new AsyncWriter()
+      {
+        @Override
+        protected void asyncWrite(Reader in) throws IOException
+        {
+          accessor.rawStore(id, size, in);
+        }
+      };
+    }
+
+    public void handleCommitInfo(long time, long previous, int branchID, String user, String comment)
+    {
+      CDOBranch branch = repository.getBranchManager().getBranch(branchID);
+      accessor.rawStore(branch, time, previous, user, comment, monitor);
+    }
+
+    public void flush()
+    {
+      accessor.rawCommit(1.0, monitor);
+    }
+
+    private void collectPackageInfos()
+    {
+      if (packageInfos != null)
+      {
+        InternalCDOPackageUnit packageUnit = packageUnits.getLast();
+        packageUnit.setPackageInfos(packageInfos.toArray(new InternalCDOPackageInfo[packageInfos.size()]));
+        packageInfos = null;
+      }
+    }
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  public static class XML extends CDOServerImporter implements CDOServerExporter.XMLConstants
+  {
+    public XML(IRepository repository)
+    {
+      super(repository);
+    }
+
+    @Override
+    protected void importAll(InputStream in, final Handler handler) throws Exception
+    {
+      DefaultHandler xmlHandler = new XMLHandler(handler);
+
+      SAXParserFactory factory = SAXParserFactory.newInstance();
+      SAXParser saxParser = factory.newSAXParser();
+      saxParser.parse(in, xmlHandler);
+    }
+
+    /**
+     * @author Eike Stepper
+     */
+    private static final class XMLHandler extends DefaultHandler
+    {
+      private Handler handler;
+
+      private InternalCDOPackageRegistry packageRegistry;
+
+      private InternalCDOBranch branch;
+
+      private InternalCDORevision revision;
+
+      private Character blobChar;
+
+      private OutputStream blob;
+
+      private Writer clob;
+
+      private XMLHandler(Handler handler)
+      {
+        this.handler = handler;
+      }
+
+      @Override
+      public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException
+      {
+        if (REPOSITORY.equals(qName))
+        {
+          String name = attributes.getValue(REPOSITORY_NAME);
+          String uuid = attributes.getValue(REPOSITORY_UUID);
+          CDOID root = id(attributes.getValue(REPOSITORY_ROOT));
+          long created = Long.parseLong(attributes.getValue(REPOSITORY_CREATED));
+          long committed = Long.parseLong(attributes.getValue(REPOSITORY_COMMITTED));
+          handler.handleRepository(name, uuid, root, created, committed);
+        }
+        else if (PACKAGE_UNIT.equals(qName))
+        {
+          String id = attributes.getValue(PACKAGE_UNIT_ID);
+          Type type = CDOPackageUnit.Type.valueOf(attributes.getValue(PACKAGE_UNIT_TYPE));
+          long time = Long.parseLong(attributes.getValue(PACKAGE_UNIT_TIME));
+          String data = attributes.getValue(PACKAGE_UNIT_DATA);
+          handler.handlePackageUnit(id, type, time, data);
+        }
+        else if (PACKAGE_INFO.equals(qName))
+        {
+          String packageURI = attributes.getValue(PACKAGE_INFO_URI);
+          handler.handlePackageInfo(packageURI);
+        }
+        else if (BRANCH.equals(qName))
+        {
+          int id = Integer.parseInt(attributes.getValue(BRANCH_ID));
+          String name = attributes.getValue(BRANCH_NAME);
+          long time = Long.parseLong(attributes.getValue(BRANCH_TIME));
+          String parent = attributes.getValue(BRANCH_PARENT);
+          int parentID = parent == null ? 0 : Integer.parseInt(parent);
+          branch = handler.handleBranch(id, name, time, parentID);
+        }
+        else if (REVISION.equals(qName))
+        {
+          CDOClassifierRef classifierRef = new CDOClassifierRef(attributes.getValue(REVISION_CLASS));
+          EClass eClass = (EClass)classifierRef.resolve(packageRegistry);
+          revision = (InternalCDORevision)CDORevisionFactory.DEFAULT.createRevision(eClass);
+          revision.setID(id(attributes.getValue(REVISION_ID)));
+          revision.setBranchPoint(branch.getPoint(Long.parseLong(attributes.getValue(REVISION_TIME))));
+          revision.setVersion(Integer.parseInt(attributes.getValue(REVISION_VERSION)));
+          String revised = attributes.getValue(REVISION_REVISED);
+          if (revised != null)
+          {
+            revision.setRevised(Long.parseLong(revised));
+          }
+
+          String resourceID = attributes.getValue(REVISION_RESOURCE);
+          if (resourceID != null)
+          {
+            revision.setResourceID(id(resourceID));
+          }
+
+          String containerID = attributes.getValue(REVISION_CONTAINER);
+          if (containerID != null)
+          {
+            revision.setContainerID(id(containerID));
+          }
+
+          String featureID = attributes.getValue(REVISION_FEATURE);
+          if (featureID != null)
+          {
+            revision.setContainingFeatureID(Integer.parseInt(featureID));
+          }
+        }
+        else if (FEATURE.equals(qName))
+        {
+          String name = attributes.getValue(FEATURE_NAME);
+          Object value = value(attributes);
+
+          EClass eClass = revision.getEClass();
+          EStructuralFeature feature = eClass.getEStructuralFeature(name);
+          if (feature == null)
+          {
+            throw new IllegalStateException("Feature " + name + " not found in class " + eClass.getName());
+          }
+
+          if (feature.isMany())
+          {
+            CDOList list = revision.getList(feature);
+            list.add(value);
+          }
+          else
+          {
+            if (value != null)
+            {
+              revision.setValue(feature, value);
+            }
+          }
+        }
+        else if (BLOB.equals(qName))
+        {
+          try
+          {
+            byte[] id = HexUtil.hexToBytes(attributes.getValue(LOB_ID));
+            long size = Long.parseLong(attributes.getValue(LOB_SIZE));
+            blob = handler.handleBlob(id, size);
+          }
+          catch (IOException ex)
+          {
+            throw WrappedException.wrap(ex);
+          }
+        }
+        else if (CLOB.equals(qName))
+        {
+          try
+          {
+            byte[] id = HexUtil.hexToBytes(attributes.getValue(LOB_ID));
+            long size = Long.parseLong(attributes.getValue(LOB_SIZE));
+            clob = handler.handleClob(id, size);
+          }
+          catch (IOException ex)
+          {
+            throw WrappedException.wrap(ex);
+          }
+        }
+        else if (COMMIT.equals(qName))
+        {
+          long time = Long.parseLong(attributes.getValue(COMMIT_TIME));
+
+          String value = attributes.getValue(COMMIT_PREVIOUS);
+          long previous = value == null ? CDOBranchPoint.UNSPECIFIED_DATE : Long.parseLong(value);
+
+          value = attributes.getValue(COMMIT_BRANCH);
+          int branch = value == null ? CDOBranch.MAIN_BRANCH_ID : Integer.parseInt(value);
+
+          String user = attributes.getValue(COMMIT_USER);
+          String comment = attributes.getValue(COMMIT_COMMENT);
+
+          handler.handleCommitInfo(time, previous, branch, user, comment);
+        }
+      }
+
+      @Override
+      public void characters(char[] ch, int start, int length) throws SAXException
+      {
+        if (blob != null)
+        {
+          try
+          {
+            if (blobChar != null)
+            {
+              char[] firstChars = { blobChar, ch[start] };
+              blobChar = null;
+
+              byte[] firstByte = HexUtil.hexToBytes(new String(firstChars));
+              blob.write(firstByte, 0, 1);
+
+              ++start;
+              --length;
+            }
+
+            if ((length & 1) == 1) // odd length?
+            {
+              --length;
+              blobChar = ch[length];
+            }
+
+            if (start != 0 || length != ch.length)
+            {
+              char[] tmp = new char[length];
+              System.arraycopy(ch, start, tmp, 0, length);
+              ch = tmp;
+            }
+
+            byte[] buf = HexUtil.hexToBytes(new String(ch));
+            blob.write(buf);
+          }
+          catch (IOException ex)
+          {
+            throw WrappedException.wrap(ex);
+          }
+        }
+        else if (clob != null)
+        {
+          try
+          {
+            clob.write(ch, start, length);
+          }
+          catch (IOException ex)
+          {
+            throw WrappedException.wrap(ex);
+          }
+        }
+      }
+
+      @Override
+      public void endElement(String uri, String localName, String qName) throws SAXException
+      {
+        if (MODELS.equals(qName))
+        {
+          packageRegistry = handler.handleModels();
+        }
+        else if (BRANCH.equals(qName))
+        {
+          branch = null;
+        }
+        else if (REVISION.equals(qName))
+        {
+          handler.handleRevision(revision);
+          revision = null;
+        }
+        else if (BLOB.equals(qName))
+        {
+          IOUtil.close(blob);
+          blob = null;
+        }
+        else if (CLOB.equals(qName))
+        {
+          IOUtil.close(clob);
+          clob = null;
+        }
+      }
+
+      protected final CDOID id(String str)
+      {
+        return CDOIDUtil.read(str);
+      }
+
+      protected Object value(Attributes attributes)
+      {
+        String type = attributes.getValue(FEATURE_TYPE);
+
+        if (TYPE_BLOB.equals(type))
+        {
+          byte[] id = HexUtil.hexToBytes(attributes.getValue(FEATURE_ID));
+          long size = Long.parseLong(attributes.getValue(FEATURE_SIZE));
+          return CDOLobUtil.createBlob(id, size);
+        }
+
+        if (TYPE_CLOB.equals(type))
+        {
+          byte[] id = HexUtil.hexToBytes(attributes.getValue(FEATURE_ID));
+          long size = Long.parseLong(attributes.getValue(FEATURE_SIZE));
+          return CDOLobUtil.createClob(id, size);
+        }
+
+        if (TYPE_FEATURE_MAP.equals(type))
+        {
+          String innerFeatureName = attributes.getValue(FEATURE_INNER_FEATURE);
+          EStructuralFeature innerFeature = revision.getEClass().getEStructuralFeature(innerFeatureName);
+
+          String innerType = attributes.getValue(FEATURE_INNER_TYPE);
+          Object innerValue = value(attributes, innerType);
+
+          return CDORevisionUtil.createFeatureMapEntry(innerFeature, innerValue);
+        }
+
+        return value(attributes, type);
+      }
+
+      protected Object value(Attributes attributes, String type)
+      {
+        String str = attributes.getValue(FEATURE_VALUE);
+        if (str == null)
+        {
+          return null;
+        }
+
+        if (type == null || String.class.getSimpleName().equals(type))
+        {
+          return str;
+        }
+
+        if (Object.class.getSimpleName().equals(type))
+        {
+          return id(str);
+        }
+
+        if (Boolean.class.getSimpleName().equals(type))
+        {
+          return Boolean.valueOf(str);
+        }
+
+        if (Character.class.getSimpleName().equals(type))
+        {
+          return str.charAt(0);
+        }
+
+        if (Byte.class.getSimpleName().equals(type))
+        {
+          return Byte.valueOf(str);
+        }
+
+        if (Short.class.getSimpleName().equals(type))
+        {
+          return Short.valueOf(str);
+        }
+
+        if (Integer.class.getSimpleName().equals(type))
+        {
+          return Integer.valueOf(str);
+        }
+
+        if (Long.class.getSimpleName().equals(type))
+        {
+          return Long.valueOf(str);
+        }
+
+        if (Float.class.getSimpleName().equals(type))
+        {
+          return Float.valueOf(str);
+        }
+
+        if (Double.class.getSimpleName().equals(type))
+        {
+          return Double.valueOf(str);
+        }
+
+        if (Date.class.getSimpleName().equals(type))
+        {
+          return new Date(Long.valueOf(str));
+        }
+
+        throw new IllegalArgumentException("Invalid type: " + type);
+      }
+    }
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/CDOServerUtil.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/CDOServerUtil.java
new file mode 100644
index 0000000..e609c53
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/CDOServerUtil.java
@@ -0,0 +1,299 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server;
+
+import org.eclipse.emf.cdo.common.CDOCommonRepository;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionManager;
+import org.eclipse.emf.cdo.common.revision.CDORevisionProvider;
+import org.eclipse.emf.cdo.internal.server.Repository;
+import org.eclipse.emf.cdo.internal.server.ServerCDOView;
+import org.eclipse.emf.cdo.internal.server.SessionManager;
+import org.eclipse.emf.cdo.internal.server.bundle.OM;
+import org.eclipse.emf.cdo.internal.server.embedded.EmbeddedClientSessionConfiguration;
+import org.eclipse.emf.cdo.internal.server.syncing.FailoverParticipant;
+import org.eclipse.emf.cdo.internal.server.syncing.OfflineClone;
+import org.eclipse.emf.cdo.internal.server.syncing.RepositorySynchronizer;
+import org.eclipse.emf.cdo.server.embedded.CDOSessionConfiguration;
+import org.eclipse.emf.cdo.session.CDOSessionConfigurationFactory;
+import org.eclipse.emf.cdo.spi.common.branch.CDOBranchUtil;
+import org.eclipse.emf.cdo.spi.common.revision.ManagedRevisionProvider;
+import org.eclipse.emf.cdo.spi.server.InternalRepositorySynchronizer;
+import org.eclipse.emf.cdo.spi.server.InternalSession;
+import org.eclipse.emf.cdo.spi.server.InternalStore;
+import org.eclipse.emf.cdo.spi.server.RepositoryFactory;
+import org.eclipse.emf.cdo.view.CDOView;
+
+import org.eclipse.net4j.util.ObjectUtil;
+import org.eclipse.net4j.util.container.IManagedContainer;
+import org.eclipse.net4j.util.lifecycle.LifecycleUtil;
+import org.eclipse.net4j.util.om.OMPlatform;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Eike Stepper
+ * @apiviz.exclude
+ */
+public final class CDOServerUtil
+{
+  private CDOServerUtil()
+  {
+  }
+
+  /**
+   * @since 4.0
+   */
+  public static CDOView openView(ISession session, CDOBranchPoint branchPoint, boolean legacyModeEnabled,
+      CDORevisionProvider revisionProvider)
+  {
+    return new ServerCDOView((InternalSession)session, branchPoint, legacyModeEnabled, revisionProvider);
+  }
+
+  /**
+   * @since 4.0
+   */
+  public static CDOView openView(ISession session, CDOBranchPoint branchPoint, boolean legacyModeEnabled)
+  {
+    CDORevisionManager revisionManager = session.getManager().getRepository().getRevisionManager();
+    CDORevisionProvider revisionProvider = new ManagedRevisionProvider(revisionManager, branchPoint);
+    return new ServerCDOView((InternalSession)session, branchPoint, legacyModeEnabled, revisionProvider);
+  }
+
+  /**
+   * @since 4.0
+   */
+  public static CDOView openView(IView view, boolean legacyModeEnabled)
+  {
+    ISession session = view.getSession();
+    CDOBranchPoint branchPoint = CDOBranchUtil.copyBranchPoint(view);
+    return openView(session, branchPoint, legacyModeEnabled, view);
+  }
+
+  /**
+   * @since 4.0
+   */
+  public static CDOView openView(IStoreAccessor.CommitContext commitContext, boolean legacyModeEnabled)
+  {
+    ISession session = commitContext.getTransaction().getSession();
+    CDOBranchPoint branchPoint = commitContext.getBranchPoint();
+    return openView(session, branchPoint, legacyModeEnabled, commitContext);
+  }
+
+  /**
+   * @since 3.0
+   */
+  public static CDOSessionConfiguration createSessionConfiguration()
+  {
+    return new EmbeddedClientSessionConfiguration();
+  }
+
+  /**
+   * @since 3.0
+   */
+  public static ISessionManager createSessionManager()
+  {
+    return new SessionManager();
+  }
+
+  public static IRepository createRepository(String name, IStore store, Map<String, String> props)
+  {
+    Repository repository = new Repository.Default();
+    initRepository(repository, name, store, props);
+    return repository;
+  }
+
+  /**
+   * @since 3.0
+   */
+  public static IRepositorySynchronizer createRepositorySynchronizer(
+      CDOSessionConfigurationFactory remoteSessionConfigurationFactory)
+  {
+    RepositorySynchronizer synchronizer = new RepositorySynchronizer();
+    synchronizer.setRemoteSessionConfigurationFactory(remoteSessionConfigurationFactory);
+    return synchronizer;
+  }
+
+  /**
+   * @since 3.0
+   */
+  public static ISynchronizableRepository createOfflineClone(String name, IStore store, Map<String, String> props,
+      IRepositorySynchronizer synchronizer)
+  {
+    OfflineClone repository = new OfflineClone();
+    initRepository(repository, name, store, props);
+    repository.setSynchronizer((InternalRepositorySynchronizer)synchronizer);
+    return repository;
+  }
+
+  /**
+   * @since 4.0
+   */
+  public static ISynchronizableRepository createFailoverParticipant(String name, IStore store,
+      Map<String, String> props, IRepositorySynchronizer synchronizer, boolean master, boolean allowBackupCommits)
+  {
+    FailoverParticipant repository = new FailoverParticipant();
+    initRepository(repository, name, store, props);
+    repository.setSynchronizer((InternalRepositorySynchronizer)synchronizer);
+    repository.setType(master ? CDOCommonRepository.Type.MASTER : CDOCommonRepository.Type.BACKUP);
+    return repository;
+  }
+
+  /**
+   * @since 3.0
+   */
+  public static ISynchronizableRepository createFailoverParticipant(String name, IStore store,
+      Map<String, String> props, IRepositorySynchronizer synchronizer, boolean master)
+  {
+    return createFailoverParticipant(name, store, props, synchronizer, master, false);
+  }
+
+  /**
+   * @since 4.0
+   */
+  public static ISynchronizableRepository createFailoverParticipant(String name, IStore store,
+      Map<String, String> props, IRepositorySynchronizer synchronizer)
+  {
+    return createFailoverParticipant(name, store, props, synchronizer, false);
+  }
+
+  /**
+   * @since 4.0
+   */
+  public static ISynchronizableRepository createFailoverParticipant(String name, IStore store, Map<String, String> props)
+  {
+    return createFailoverParticipant(name, store, props, null);
+  }
+
+  private static void initRepository(Repository repository, String name, IStore store, Map<String, String> props)
+  {
+    repository.setName(name);
+    repository.setStore((InternalStore)store);
+    repository.setProperties(props);
+  }
+
+  public static void addRepository(IManagedContainer container, IRepository repository)
+  {
+    container.putElement(RepositoryFactory.PRODUCT_GROUP, RepositoryFactory.TYPE, repository.getName(), repository);
+    LifecycleUtil.activate(repository);
+  }
+
+  public static IRepository getRepository(IManagedContainer container, String name)
+  {
+    return RepositoryFactory.get(container, name);
+  }
+
+  public static Element getRepositoryConfig(String repositoryName) throws ParserConfigurationException, SAXException,
+      IOException
+  {
+    File configFile = OMPlatform.INSTANCE.getConfigFile("cdo-server.xml"); //$NON-NLS-1$
+
+    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+    DocumentBuilder builder = factory.newDocumentBuilder();
+    Document document = builder.parse(configFile);
+    NodeList elements = document.getElementsByTagName("repository"); //$NON-NLS-1$
+    for (int i = 0; i < elements.getLength(); i++)
+    {
+      Node node = elements.item(i);
+      if (node instanceof Element)
+      {
+        Element element = (Element)node;
+        String name = element.getAttribute("name"); //$NON-NLS-1$
+        if (ObjectUtil.equals(name, repositoryName))
+        {
+          return element;
+        }
+      }
+    }
+
+    throw new IllegalStateException("Repository config not found: " + repositoryName); //$NON-NLS-1$
+  }
+
+  /**
+   * @author Eike Stepper
+   * @since 2.0
+   * @apiviz.exclude
+   */
+  public static abstract class RepositoryReadAccessValidator implements IRepository.ReadAccessHandler
+  {
+    public RepositoryReadAccessValidator()
+    {
+    }
+
+    public void handleRevisionsBeforeSending(ISession session, CDORevision[] revisions,
+        List<CDORevision> additionalRevisions) throws RuntimeException
+    {
+      List<String> violations = new ArrayList<String>();
+      for (CDORevision revision : revisions)
+      {
+        String violation = validate(session, revision);
+        if (violation != null)
+        {
+          violations.add(violation);
+        }
+      }
+
+      if (!violations.isEmpty())
+      {
+        throwException(session, violations);
+      }
+
+      for (Iterator<CDORevision> it = additionalRevisions.iterator(); it.hasNext();)
+      {
+        CDORevision revision = it.next();
+        String violation = validate(session, revision);
+        if (violation != null)
+        {
+          OM.LOG.info("Revision can not be delivered to " + session + ": " + violation); //$NON-NLS-1$ //$NON-NLS-2$
+          it.remove();
+        }
+      }
+    }
+
+    protected void throwException(ISession session, List<String> violations) throws RuntimeException
+    {
+      StringBuilder builder = new StringBuilder();
+      builder.append("Revisions can not be delivered to "); //$NON-NLS-1$
+      builder.append(session);
+      builder.append(":"); //$NON-NLS-1$
+      for (String violation : violations)
+      {
+        builder.append("\n- "); //$NON-NLS-1$
+        builder.append(violation);
+      }
+
+      throwException(builder.toString());
+    }
+
+    protected void throwException(String message) throws RuntimeException
+    {
+      throw new IllegalStateException(message);
+    }
+
+    protected abstract String validate(ISession session, CDORevision revision);
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/ContainmentCycleDetectedException.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/ContainmentCycleDetectedException.java
new file mode 100644
index 0000000..0a71e68
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/ContainmentCycleDetectedException.java
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server;
+
+/**
+ * @author Eike Stepper
+ * @since 4.0
+ */
+public class ContainmentCycleDetectedException extends IllegalStateException
+{
+  private static final long serialVersionUID = 1L;
+
+  public ContainmentCycleDetectedException()
+  {
+  }
+
+  public ContainmentCycleDetectedException(String message, Throwable cause)
+  {
+    super(message, cause);
+  }
+
+  public ContainmentCycleDetectedException(String s)
+  {
+    super(s);
+  }
+
+  public ContainmentCycleDetectedException(Throwable cause)
+  {
+    super(cause);
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IMEMStore.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IMEMStore.java
new file mode 100644
index 0000000..d73f1ec
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IMEMStore.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server;
+
+/**
+ * A simple in-memory store.
+ * 
+ * @author Eike Stepper
+ * @since 2.0
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ * @deprecated Use {@link org.eclipse.emf.cdo.server.mem.IMEMStore}
+ * @apiviz.exclude
+ */
+@Deprecated
+public interface IMEMStore extends org.eclipse.emf.cdo.server.mem.IMEMStore
+{
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IQueryContext.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IQueryContext.java
new file mode 100644
index 0000000..9752d12
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IQueryContext.java
@@ -0,0 +1,41 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+
+/**
+ * @author Eike Stepper
+ * @since 2.0
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ * @apiviz.exclude
+ */
+public interface IQueryContext extends CDOBranchPoint
+{
+  public IView getView();
+
+  /**
+   * @since 4.0
+   */
+  public int getResultCount();
+
+  /**
+   * Adds the given object to the results of the associated query.
+   * 
+   * @param object
+   *          Support many primitives, CDOID and CDORevision. CDORevision are converted in CDOID and only CDOID are
+   *          transfered to the client.
+   * @return <code>true</code> to indicate that more results can be passed subsequently, <code>false</code> otherwise
+   *         (i.e. maxResults has been reached or an asynchronous query has been canceled).
+   */
+  public boolean addResult(Object object);
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IQueryHandler.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IQueryHandler.java
new file mode 100644
index 0000000..65e2795
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IQueryHandler.java
@@ -0,0 +1,25 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server;
+
+import org.eclipse.emf.cdo.common.util.CDOQueryInfo;
+
+/**
+ * @author Eike Stepper
+ * @since 2.0
+ */
+public interface IQueryHandler
+{
+  /**
+   * @since 3.0
+   */
+  public void executeQuery(CDOQueryInfo info, IQueryContext context);
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IQueryHandlerProvider.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IQueryHandlerProvider.java
new file mode 100644
index 0000000..944d2d7
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IQueryHandlerProvider.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server;
+
+import org.eclipse.emf.cdo.common.util.CDOQueryInfo;
+
+/**
+ * @author Eike Stepper
+ * @since 2.0
+ * @apiviz.uses {@link IQueryHandler} - - provides
+ */
+public interface IQueryHandlerProvider
+{
+  /**
+   * @since 3.0
+   */
+  public IQueryHandler getQueryHandler(CDOQueryInfo info);
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IRepository.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IRepository.java
new file mode 100644
index 0000000..a9d8de7
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IRepository.java
@@ -0,0 +1,264 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server;
+
+import org.eclipse.emf.cdo.common.CDOCommonRepository;
+import org.eclipse.emf.cdo.common.branch.CDOBranchManager;
+import org.eclipse.emf.cdo.common.commit.CDOCommitInfoHandler;
+import org.eclipse.emf.cdo.common.lock.IDurableLockingManager;
+import org.eclipse.emf.cdo.common.model.CDOPackageRegistry;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionManager;
+
+import org.eclipse.net4j.util.container.IContainer;
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EPackage.Registry;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Eike Stepper
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ * @apiviz.landmark
+ * @apiviz.has {@link IStore}
+ * @apiviz.has {@link java.util.Map} oneway - - properties
+ * @apiviz.has {@link org.eclipse.emf.cdo.common.model.CDOPackageRegistry}
+ * @apiviz.has {@link org.eclipse.emf.cdo.common.branch.CDOBranchManager}
+ * @apiviz.has {@link org.eclipse.emf.cdo.common.revision.CDORevisionManager}
+ * @apiviz.has {@link org.eclipse.emf.cdo.common.lock.IDurableLockingManager}
+ * @apiviz.has {@link ISessionManager}
+ * @apiviz.has {@link IQueryHandlerProvider}
+ * @apiviz.composedOf {@link org.eclipse.emf.cdo.common.commit.CDOCommitInfoHandler}
+ * @apiviz.composedOf {@link IRepository.Handler} - - accessHandlers
+ */
+public interface IRepository extends CDOCommonRepository, IQueryHandlerProvider, IContainer<Object>
+{
+  /**
+   * @since 3.0
+   */
+  public static final String SYSTEM_USER_ID = "CDO_SYSTEM"; //$NON-NLS-1$
+
+  public IStore getStore();
+
+  public Map<String, String> getProperties();
+
+  /**
+   * Returns the EMF {@link Registry package registry} that is used by this repository.
+   * 
+   * @since 2.0
+   */
+  public CDOPackageRegistry getPackageRegistry();
+
+  /**
+   * @since 3.0
+   */
+  public CDOBranchManager getBranchManager();
+
+  /**
+   * @since 3.0
+   */
+  public CDORevisionManager getRevisionManager();
+
+  public ISessionManager getSessionManager();
+
+  /**
+   * @since 4.0
+   */
+  public IDurableLockingManager getLockManager();
+
+  /**
+   * @since 2.0
+   */
+  public IQueryHandlerProvider getQueryHandlerProvider();
+
+  /**
+   * Returns the time stamp of the last commit operation.
+   * 
+   * @since 3.0
+   */
+  public long getLastCommitTimeStamp();
+
+  /**
+   * Blocks the calling thread until the next commit operation has succeeded and returns the last (highest) commit time
+   * stamp.
+   * 
+   * @since 3.0
+   */
+  public long waitForCommit(long timeout);
+
+  /**
+   * Validates the given timeStamp against the repository time.
+   * 
+   * @throws IllegalArgumentException
+   *           if the given timeStamp is less than the repository creation time or greater than the current repository
+   *           time.
+   * @since 2.0
+   */
+  public void validateTimeStamp(long timeStamp) throws IllegalArgumentException;
+
+  /**
+   * @since 4.0
+   */
+  public void addCommitInfoHandler(CDOCommitInfoHandler handler);
+
+  /**
+   * @since 4.0
+   */
+  public void removeCommitInfoHandler(CDOCommitInfoHandler handler);
+
+  /**
+   * @since 2.0
+   */
+  public void addHandler(Handler handler);
+
+  /**
+   * @since 2.0
+   */
+  public void removeHandler(Handler handler);
+
+  /**
+   * @since 4.0
+   */
+  public void setInitialPackages(EPackage... initialPackages);
+
+  /**
+   * A marker interface to indicate valid arguments to {@link IRepository#addHandler(Handler)} and
+   * {@link IRepository#removeHandler(Handler)}.
+   * 
+   * @see ReadAccessHandler
+   * @see WriteAccessHandler
+   * @author Eike Stepper
+   * @since 2.0
+   */
+  public interface Handler
+  {
+  }
+
+  /**
+   * Provides a way to handle revisions that are to be sent to the client.
+   * 
+   * @author Eike Stepper
+   * @since 2.0
+   */
+  public interface ReadAccessHandler extends Handler
+  {
+    /**
+     * Provides a way to handle revisions that are to be sent to the client.
+     * 
+     * @param session
+     *          The session that is going to send the revisions.
+     * @param revisions
+     *          The revisions that are requested by the client. If the client must not see any of these revisions an
+     *          unchecked exception must be thrown.
+     * @param additionalRevisions
+     *          The additional revisions that are to be sent to the client because internal optimizers believe that they
+     *          will be needed soon. If the client must not see any of these revisions they should be removed from the
+     *          list.
+     * @throws RuntimeException
+     *           to indicate that none of the revisions must be sent to the client. This exception will be visible at
+     *           the client side!
+     */
+    public void handleRevisionsBeforeSending(ISession session, CDORevision[] revisions,
+        List<CDORevision> additionalRevisions) throws RuntimeException;
+  }
+
+  /**
+   * @author Eike Stepper
+   * @since 2.0
+   */
+  public interface WriteAccessHandler extends Handler
+  {
+    /**
+     * Provides a way to handle transactions that are to be committed to the backend store.
+     * 
+     * @param transaction
+     *          The transaction that is going to be committed.
+     * @param commitContext
+     *          The context of the commit operation that is to be executed against the backend store. The context can be
+     *          used to introspect all aspects of the current commit operation. <b>Note that you must not alter the
+     *          internal state of the commit context in any way!</b>
+     * @param monitor
+     *          A monitor that should be used by the implementor to avoid timeouts.
+     * @throws RuntimeException
+     *           to indicate that the commit operation must not be executed against the backend store. This exception
+     *           will be visible at the client side!
+     */
+    public void handleTransactionBeforeCommitting(ITransaction transaction, IStoreAccessor.CommitContext commitContext,
+        OMMonitor monitor) throws RuntimeException;
+
+    /**
+     * Provides a way to handle transactions after they have been committed to the backend store.
+     * 
+     * @param transaction
+     *          The transaction that has been committed.
+     * @param commitContext
+     *          The context of the commit operation that was executed against the backend store. The context can be used
+     *          to introspect all aspects of the current commit operation. <b>Note that you must not alter the internal
+     *          state of the commit context in any way!</b>
+     * @param monitor
+     *          A monitor that should be used by the implementor to avoid timeouts.
+     * @since 3.0
+     */
+    public void handleTransactionAfterCommitted(ITransaction transaction, IStoreAccessor.CommitContext commitContext,
+        OMMonitor monitor);
+  }
+
+  /**
+   * @author Eike Stepper
+   * @noimplement This interface is not intended to be implemented by clients.
+   * @noextend This interface is not intended to be extended by clients.
+   * @apiviz.exclude
+   */
+  public interface Props
+  {
+    /**
+     * Used to override the automatic UUID generation during first startup of a repository. Passing the empty string
+     * causes the UUID of the repository to be set to its {@link IRepository#getName() name}.
+     * 
+     * @since 2.0
+     */
+    public static final String OVERRIDE_UUID = "overrideUUID"; //$NON-NLS-1$
+
+    /**
+     * @since 2.0
+     */
+    public static final String SUPPORTING_AUDITS = "supportingAudits"; //$NON-NLS-1$
+
+    /**
+     * @since 3.0
+     */
+    public static final String SUPPORTING_BRANCHES = "supportingBranches"; //$NON-NLS-1$
+
+    /**
+     * @since 4.0
+     */
+    public static final String SUPPORTING_ECORE = "supportingEcore"; //$NON-NLS-1$
+
+    /**
+     * @since 3.0
+     */
+    public static final String ENSURE_REFERENTIAL_INTEGRITY = "ensureReferentialIntegrity"; //$NON-NLS-1$
+
+    /**
+     * @since 4.0
+     */
+    public static final String ALLOW_INTERRUPT_RUNNING_QUERIES = "allowInterruptRunningQueries"; //$NON-NLS-1$
+
+    /**
+     * @since 4.1
+     */
+    public static final String ID_GENERATION_LOCATION = "idGenerationLocation"; //$NON-NLS-1$
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IRepositoryFactory.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IRepositoryFactory.java
new file mode 100644
index 0000000..9e2d276
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IRepositoryFactory.java
@@ -0,0 +1,27 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server;
+
+/**
+ * @author Eike Stepper
+ * @apiviz.uses {@link IRepository} - - creates
+ */
+public interface IRepositoryFactory
+{
+  /**
+   * @since 2.0
+   */
+  public static final String PRODUCT_GROUP = "org.eclipse.emf.cdo.server.repositories"; //$NON-NLS-1$
+
+  public String getRepositoryType();
+
+  public IRepository createRepository();
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IRepositoryProvider.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IRepositoryProvider.java
new file mode 100644
index 0000000..3367750
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IRepositoryProvider.java
@@ -0,0 +1,20 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server;
+
+/**
+ * @author Eike Stepper
+ * @apiviz.uses {@link IRepository} - - provides
+ */
+public interface IRepositoryProvider
+{
+  public IRepository getRepository(String name);
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IRepositorySynchronizer.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IRepositorySynchronizer.java
new file mode 100644
index 0000000..cae1cc8
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IRepositorySynchronizer.java
@@ -0,0 +1,52 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server;
+
+import org.eclipse.emf.cdo.session.CDOSession;
+import org.eclipse.emf.cdo.session.CDOSessionConfigurationFactory;
+
+import org.eclipse.net4j.util.event.INotifier;
+
+/**
+ * @author Eike Stepper
+ * @since 3.0
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ * @apiviz.landmark
+ * @apiviz.has {@link org.eclipse.emf.cdo.session.CDOSessionConfigurationFactory} oneway - - remote
+ */
+public interface IRepositorySynchronizer extends INotifier
+{
+  public int getRetryInterval();
+
+  public void setRetryInterval(int retryInterval);
+
+  public ISynchronizableRepository getLocalRepository();
+
+  public CDOSessionConfigurationFactory getRemoteSessionConfigurationFactory();
+
+  public CDOSession getRemoteSession();
+
+  public boolean isRawReplication();
+
+  /**
+   * @since 4.0
+   */
+  public void setRawReplication(boolean rawReplication);
+
+  public int getMaxRecommits();
+
+  public void setMaxRecommits(int maxRecommits);
+
+  public int getRecommitInterval();
+
+  public void setRecommitInterval(int recommitInterval);
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/ISession.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/ISession.java
new file mode 100644
index 0000000..386af3d
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/ISession.java
@@ -0,0 +1,60 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Simon McDuff - bug 230832
+ */
+package org.eclipse.emf.cdo.server;
+
+import org.eclipse.emf.cdo.common.CDOCommonSession;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.spi.server.ISessionProtocol;
+
+import org.eclipse.net4j.util.container.IContainer;
+
+/**
+ * @author Eike Stepper
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ * @apiviz.landmark
+ * @apiviz.has {@link org.eclipse.emf.cdo.spi.server.ISessionProtocol}
+ * @apiviz.composedOf {@link IView} - - views
+ * @apiviz.composedOf {@link ITransaction} - - transactions
+ */
+public interface ISession extends CDOCommonSession, IContainer<IView>
+{
+  /**
+   * @since 3.0
+   */
+  public ISessionManager getManager();
+
+  /**
+   * @since 3.0
+   */
+  public ISessionProtocol getProtocol();
+
+  /**
+   * @since 4.0
+   */
+  public long getLastUpdateTime();
+
+  /**
+   * @since 2.0
+   */
+  public boolean isSubscribed();
+
+  /**
+   * @since 3.0
+   */
+  public IView openView(int viewID, CDOBranchPoint branchPoint);
+
+  /**
+   * @since 3.0
+   */
+  public ITransaction openTransaction(int viewID, CDOBranchPoint branchPoint);
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/ISessionManager.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/ISessionManager.java
new file mode 100644
index 0000000..795a835
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/ISessionManager.java
@@ -0,0 +1,35 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server;
+
+import org.eclipse.net4j.util.container.IContainer;
+
+/**
+ * @author Eike Stepper
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ * @apiviz.landmark
+ * @apiviz.composedOf {@link ISession}
+ */
+public interface ISessionManager extends IContainer<ISession>
+{
+  /**
+   * @since 2.0
+   */
+  public IRepository getRepository();
+
+  public ISession[] getSessions();
+
+  /**
+   * @since 2.0
+   */
+  public ISession getSession(int sessionID);
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IStore.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IStore.java
new file mode 100644
index 0000000..a94202d
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IStore.java
@@ -0,0 +1,213 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server;
+
+import org.eclipse.emf.cdo.common.CDOCommonRepository.IDGenerationLocation;
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.id.CDOID.ObjectType;
+
+import org.eclipse.net4j.util.om.monitor.ProgressDistributor;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author Eike Stepper
+ * @apiviz.landmark
+ * @apiviz.has {@link IStore.ChangeFormat}
+ * @apiviz.has {@link IStore.RevisionTemporality}
+ * @apiviz.has {@link IStore.RevisionParallelism}
+ * @apiviz.uses {@link IStoreAccessor} - - creates
+ */
+public interface IStore
+{
+  /**
+   * @since 2.0
+   */
+  public IRepository getRepository();
+
+  /**
+   * @since 2.0
+   */
+  public String getType();
+
+  /**
+   * @since 3.0
+   */
+  public Set<CDOID.ObjectType> getObjectIDTypes();
+
+  /**
+   * @since 4.0
+   */
+  public CDOID createObjectID(String val);
+
+  /**
+   * @since 2.0
+   */
+  public Set<ChangeFormat> getSupportedChangeFormats();
+
+  /**
+   * @since 2.0
+   */
+  public Set<RevisionTemporality> getSupportedRevisionTemporalities();
+
+  /**
+   * @since 2.0
+   */
+  public Set<RevisionParallelism> getSupportedRevisionParallelisms();
+
+  /**
+   * @since 2.0
+   */
+  public RevisionTemporality getRevisionTemporality();
+
+  /**
+   * @since 2.0
+   */
+  public RevisionParallelism getRevisionParallelism();
+
+  /**
+   * Returns <code>true</code>if this store was activated for the first time, <code>false</code> otherwise.
+   * 
+   * @since 4.0
+   */
+  public boolean isFirstStart();
+
+  /**
+   * Returns the store creation time.
+   * 
+   * @since 2.0
+   */
+  public long getCreationTime();
+
+  /**
+   * Returns the id of the last branch that has been created in this store.
+   * 
+   * @since 3.0
+   */
+  public int getLastBranchID();
+
+  /**
+   * Returns the id of the last local branch that has been created in this store.
+   * 
+   * @since 3.0
+   */
+  public int getLastLocalBranchID();
+
+  /**
+   * Returns the time stamp of the last successful commit operation.
+   * 
+   * @since 3.0
+   */
+  public long getLastCommitTime();
+
+  /**
+   * Returns the time stamp of the last successful commit operation to a non-local {@link CDOBranch branch}.
+   * 
+   * @since 3.0
+   */
+  public long getLastNonLocalCommitTime();
+
+  /**
+   * Returns a map filled with the property entries for the requested property <code>names</code> if names is not
+   * <code>null</code> and not {@link Collection#isEmpty() empty}, all existing property entries otherwise.
+   * 
+   * @since 4.0
+   */
+  public Map<String, String> getPersistentProperties(Set<String> names);
+
+  /**
+   * @since 4.0
+   */
+  public void setPersistentProperties(Map<String, String> properties);
+
+  /**
+   * @since 4.0
+   */
+  public void removePersistentProperties(Set<String> names);
+
+  /**
+   * Returns a reader that can be used to read from this store in the context of the given session.
+   * 
+   * @param session
+   *          The session that should be used as a context for read access or <code>null</code>. The store implementor
+   *          is free to interpret and use the session in a manner suitable for him or ignore it at all. It is meant
+   *          only as a hint. Implementor can use it as a key into a cache and/or register a
+   *          {@link org.eclipse.net4j.util.lifecycle.LifecycleEventAdapter LifecycleEventAdapter} with it to intercept
+   *          cleanup on session close. Note however that the session can be <code>null</code>, for example during
+   *          startup of the server while the repositories are initialized but before any user session has been opened.
+   * @return a reader that can be used to read from this store in the context of the given session, never
+   *         <code>null</code>.
+   * @since 2.0
+   */
+  public IStoreAccessor getReader(ISession session);
+
+  /**
+   * Returns a writer that can be used to write to this store in the context of the given view. The given view is always
+   * marked as a transaction.
+   * 
+   * @param transaction
+   *          The view that must be used as a context for write access. The store implementor is free to interpret and
+   *          use the view in a manner suitable for him or ignore it at all. It is meant only as a hint. Implementor can
+   *          use it as a key into a cache and/or register a
+   *          {@link org.eclipse.net4j.util.lifecycle.LifecycleEventAdapter LifecycleEventAdapter} with it to intercept
+   *          cleanup on view close.
+   * @return a writer that can be used to write to this store in the context of the given view, never <code>null</code>.
+   * @since 2.0
+   */
+  public IStoreAccessor getWriter(ITransaction transaction);
+
+  /**
+   * @since 2.0
+   */
+  public ProgressDistributor getIndicatingCommitDistributor();
+
+  /**
+   * @author Eike Stepper
+   * @since 2.0
+   */
+  public enum ChangeFormat
+  {
+    REVISION, DELTA
+  }
+
+  /**
+   * @author Eike Stepper
+   * @since 2.0
+   */
+  public enum RevisionTemporality
+  {
+    NONE, AUDITING
+  }
+
+  /**
+   * @author Eike Stepper
+   * @since 2.0
+   */
+  public enum RevisionParallelism
+  {
+    NONE, BRANCHING
+  }
+
+  /**
+   * A marker interface for {@link IStore stores} that can handle {@link CDOID IDs} assigned by a
+   * {@link IDGenerationLocation#CLIENT client}, typically {@link ObjectType#UUID UUIDs}.
+   * 
+   * @author Eike Stepper
+   * @since 4.1
+   * @apiviz.exclude
+   */
+  public interface CanHandleClientAssignedIDs
+  {
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IStoreAccessor.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IStoreAccessor.java
new file mode 100644
index 0000000..960a813
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IStoreAccessor.java
@@ -0,0 +1,729 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.branch.CDOBranchVersion;
+import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.id.CDOIDReference;
+import org.eclipse.emf.cdo.common.lob.CDOBlob;
+import org.eclipse.emf.cdo.common.lob.CDOClob;
+import org.eclipse.emf.cdo.common.lob.CDOLob;
+import org.eclipse.emf.cdo.common.lob.CDOLobHandler;
+import org.eclipse.emf.cdo.common.lock.IDurableLockingManager;
+import org.eclipse.emf.cdo.common.model.CDOPackageUnit;
+import org.eclipse.emf.cdo.common.protocol.CDODataInput;
+import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
+import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionCacheAdder;
+import org.eclipse.emf.cdo.common.revision.CDORevisionHandler;
+import org.eclipse.emf.cdo.common.revision.CDORevisionKey;
+import org.eclipse.emf.cdo.common.revision.CDORevisionProvider;
+import org.eclipse.emf.cdo.common.util.CDOQueryInfo;
+import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranchManager.BranchLoader;
+import org.eclipse.emf.cdo.spi.common.commit.CDOChangeSetSegment;
+import org.eclipse.emf.cdo.spi.common.commit.InternalCDOCommitInfoManager.CommitInfoLoader;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionDelta;
+import org.eclipse.emf.cdo.spi.server.InternalCommitContext;
+import org.eclipse.emf.cdo.spi.server.InternalSession;
+
+import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
+import org.eclipse.net4j.util.concurrent.RWOLockManager.LockState;
+import org.eclipse.net4j.util.io.ExtendedDataInputStream;
+import org.eclipse.net4j.util.io.IOUtil;
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author Eike Stepper
+ * @apiviz.uses {@link IStoreChunkReader} - - creates
+ */
+public interface IStoreAccessor extends IQueryHandlerProvider, BranchLoader, CommitInfoLoader
+{
+  /**
+   * Returns the store this accessor is associated with.
+   */
+  public IStore getStore();
+
+  /**
+   * Returns the session this accessor is associated with.
+   * 
+   * @since 3.0
+   */
+  public InternalSession getSession();
+
+  /**
+   * Returns the transaction this accessor is associated with if {@link #isReader()} returns <code>false</code>,
+   * <code>null</code> otherwise.
+   * 
+   * @since 2.0
+   */
+  public ITransaction getTransaction();
+
+  /**
+   * Returns <code>true</code> if this accessor has been configured for read-only access to the back-end,
+   * <code>false</code> otherwise.
+   * 
+   * @since 2.0
+   */
+  public boolean isReader();
+
+  /**
+   * @since 2.0
+   */
+  public IStoreChunkReader createChunkReader(InternalCDORevision revision, EStructuralFeature feature);
+
+  /**
+   * @since 2.0
+   */
+  public Collection<InternalCDOPackageUnit> readPackageUnits();
+
+  /**
+   * Demand loads a given package proxy that has been created on startup of the repository.
+   * <p>
+   * This method must only load the given package, <b>not</b> possible contained packages.
+   * 
+   * @since 2.0
+   */
+  public EPackage[] loadPackageUnit(InternalCDOPackageUnit packageUnit);
+
+  /**
+   * Reads a revision from the back-end that was valid at the given timeStamp in the given branch.
+   * 
+   * @since 4.0
+   */
+  public InternalCDORevision readRevision(CDOID id, CDOBranchPoint branchPoint, int listChunk,
+      CDORevisionCacheAdder cache);
+
+  /**
+   * Reads a revision with the given version in the given branch from the back-end.
+   * 
+   * @since 4.0
+   */
+  public InternalCDORevision readRevisionByVersion(CDOID id, CDOBranchVersion branchVersion, int listChunk,
+      CDORevisionCacheAdder cache);
+
+  /**
+   * Passes all revisions of the store to the {@link CDORevisionHandler handler} if <b>all</b> of the following
+   * conditions are met:
+   * <ul>
+   * <li>The <code>eClass</code> parameter is <code>null</code> or equal to <code>revision.getEClass()</code>.
+   * <li>The <code>branch</code> parameter is <code>null</code> or equal to <code>revision.getBranch()</code>.
+   * <li><b>One</b> of the following conditions is met:
+   * <ul>
+   * <li>The <code>timeStamp</code> parameter is {@link CDOBranchPoint#INVALID_DATE INVALID}.
+   * <li>The <code>exactTime</code> parameter is <code>true</code> and the <code>timeStamp</code> parameter is
+   * {@link CDOBranchPoint#UNSPECIFIED_DATE UNSPECIFIED} or equal to <code>revision.getTimeStamp()</code>.
+   * <li>The <code>exactTime</code> parameter is <code>false</code> and the <code>timeStamp</code> parameter is between
+   * <code>revision.getTimeStamp()</code> and <code>revision.getRevised()</code>.
+   * </ul>
+   * </ul>
+   * 
+   * @since 4.0
+   */
+  public void handleRevisions(EClass eClass, CDOBranch branch, long timeStamp, boolean exactTime,
+      CDORevisionHandler handler);
+
+  /**
+   * Returns a set of CDOIDs that have at least one revision in any of the passed branches and time ranges.
+   * DetachedCDORevisions must also be considered!
+   * 
+   * @since 4.0
+   */
+  public Set<CDOID> readChangeSet(OMMonitor monitor, CDOChangeSetSegment... segments);
+
+  /**
+   * Returns the <code>CDOID</code> of the resource node with the given folderID and name if a resource with this
+   * folderID and name exists in the store, <code>null</code> otherwise.
+   * 
+   * @since 3.0
+   */
+  public CDOID readResourceID(CDOID folderID, String name, CDOBranchPoint branchPoint);
+
+  /**
+   * @since 2.0
+   */
+  public void queryResources(QueryResourcesContext context);
+
+  /**
+   * @since 3.0
+   */
+  public void queryXRefs(QueryXRefsContext context);
+
+  /**
+   * Determines which of the large objects identified by the given {@link CDOLob#getID() IDs} are known in the backend
+   * represented by this {@link IStoreAccessor} by removing the unknown IDs from the passed collection.
+   * <p>
+   * The identifier of a {@link CDOLob large object} is the SHA-1 digest of the content of this large object.
+   * <p>
+   * <b>Usage context:</b> This method is only called in the context of a commit operation of a client transaction if
+   * that transaction contains additions of or changes to large objects.
+   * 
+   * @param ids
+   *          the collection of large object IDs that the unknown IDs are supposed to be removed from.
+   * @since 4.0
+   */
+  public void queryLobs(List<byte[]> ids);
+
+  /**
+   * Serializes the content of the large object identified by the given {@link CDOLob#getID() ID} to the given
+   * <i>stream</i>.
+   * <p>
+   * The identifier of a {@link CDOLob large object} is the SHA-1 digest of the content of this large object.
+   * 
+   * @param id
+   *          the ID of the large object whose content is to be written to the <i>stream</i>.
+   * @throws IOException
+   *           if the <i>stream</i> could not be written to.
+   * @since 4.0
+   */
+  public void loadLob(byte[] id, OutputStream out) throws IOException;
+
+  /**
+   * @since 4.0
+   */
+  public void handleLobs(long fromTime, long toTime, CDOLobHandler handler) throws IOException;
+
+  /**
+   * @since 2.0
+   */
+  public void writePackageUnits(InternalCDOPackageUnit[] packageUnits, OMMonitor monitor);
+
+  /**
+   * Called before committing. An instance of this accessor represents an instance of a back-end transaction. Could be
+   * called multiple times before commit it called. {@link IStoreAccessor#commit(OMMonitor)} or
+   * {@link IStoreAccessor#rollback()} will be called after any numbers of
+   * {@link IStoreAccessor#write(InternalCommitContext, OMMonitor)}.
+   * <p>
+   * <b>Note</b>: {@link IStoreAccessor#write(InternalCommitContext, OMMonitor)} and
+   * {@link IStoreAccessor#commit(OMMonitor)} could be called from different threads.
+   * 
+   * @since 3.0
+   */
+  public void write(InternalCommitContext context, OMMonitor monitor);
+
+  /**
+   * Flushes to the back-end and makes available the data for others.
+   * <p>
+   * <b>Note</b>: {@link IStoreAccessor#write(InternalCommitContext, OMMonitor)} and
+   * {@link IStoreAccessor#commit(OMMonitor)} could be called from different threads.
+   * <p>
+   * <b>Note</b>: Implementors should detect if dirty write occurred. In this case it should throw an exception.
+   * 
+   * <pre>
+   * if (revision.getVersion() != revisionDelta.getOriginVersion())
+   * {
+   *   throw new ConcurrentModificationException(&quot;Trying to update object &quot; + revisionDelta.getID()
+   *       + &quot; that was already modified&quot;);
+   * }
+   * </pre>
+   * 
+   * @since 2.0
+   */
+  public void commit(OMMonitor monitor);
+
+  /**
+   * <b>Note</b>: {@link IStoreAccessor#write(InternalCommitContext, OMMonitor)} and {@link IStoreAccessor#rollback()}
+   * could be called from different threads.
+   * 
+   * @since 2.0
+   */
+  public void rollback();
+
+  public void release();
+
+  /**
+   * Represents the state of a single, logical commit operation which is driven through multiple calls to several
+   * methods on the {@link IStoreAccessor} API. All these method calls get the same <code>CommitContext</code> instance
+   * passed so that the implementor of the {@link IStoreAccessor} can track the state and progress of the commit
+   * operation.
+   * 
+   * @author Eike Stepper
+   * @since 2.0
+   * @noimplement This interface is not intended to be implemented by clients.
+   * @apiviz.exclude
+   */
+  public interface CommitContext extends CDORevisionProvider
+  {
+    /**
+     * Returns the transactional view (<code>ITransaction</code>) which is the scope of the commit operation represented
+     * by this <code>CommitContext</code>.
+     * 
+     * @since 4.0
+     */
+    public ITransaction getTransaction();
+
+    /**
+     * Returns the branch ID and timestamp of this commit operation.
+     * 
+     * @since 3.0
+     */
+    public CDOBranchPoint getBranchPoint();
+
+    /**
+     * @since 4.0
+     */
+    public long getPreviousTimeStamp();
+
+    /**
+     * @since 3.0
+     */
+    public String getUserID();
+
+    /**
+     * @since 3.0
+     */
+    public String getCommitComment();
+
+    /**
+     * @since 3.0
+     */
+    public boolean isAutoReleaseLocksEnabled();
+
+    /**
+     * Returns the temporary, transactional package manager associated with the commit operation represented by this
+     * <code>CommitContext</code>. In addition to the packages registered with the session this package manager also
+     * contains the new packages that are part of this commit operation.
+     */
+    public InternalCDOPackageRegistry getPackageRegistry();
+
+    /**
+     * Returns an array of the new package units that are part of the commit operation represented by this
+     * <code>CommitContext</code>.
+     */
+    public InternalCDOPackageUnit[] getNewPackageUnits();
+
+    /**
+     * Returns an array of the new objects that are part of the commit operation represented by this
+     * <code>CommitContext</code>.
+     */
+    public InternalCDORevision[] getNewObjects();
+
+    /**
+     * Returns an array of the dirty objects that are part of the commit operation represented by this
+     * <code>CommitContext</code>.
+     */
+    public InternalCDORevision[] getDirtyObjects();
+
+    /**
+     * Returns an array of the dirty object deltas that are part of the commit operation represented by this
+     * <code>CommitContext</code>.
+     */
+    public InternalCDORevisionDelta[] getDirtyObjectDeltas();
+
+    /**
+     * Returns an array of the removed object that are part of the commit operation represented by this
+     * <code>CommitContext</code>.
+     * 
+     * @since 2.0
+     */
+    public CDOID[] getDetachedObjects();
+
+    /**
+     * Returns a map with an {@link EClass} value per {@link CDOID} type.
+     * 
+     * @since 4.0
+     */
+    public Map<CDOID, EClass> getDetachedObjectTypes();
+
+    /**
+     * Returns a stream that all {@link CDOLob lobs} can be read from. The format of the data delivered through the
+     * stream is:
+     * <p>
+     * <ol>
+     * <li> {@link ExtendedDataInputStream#readInt() int}: the number of lobs to be read from the stream.
+     * <li>The following data can be read from the stream in a loop with one iteration per lob in the stream:
+     * <ol>
+     * <li> {@link ExtendedDataInputStream#readByteArray() int + byte[]}: the id of the lob (prepended by the size of the
+     * id).
+     * <li> {@link ExtendedDataInputStream#readLong() long}: the size of the lob. The foollowing interpretation applies:
+     * <ul>
+     * <li>A positive size indicates a {@link CDOBlob blob} and means the number of bytes that can be
+     * {@link IOUtil#copyBinary(java.io.InputStream, java.io.OutputStream) read}.
+     * <li>A negative size indicates a {@link CDOClob clob} and means the number of characters that can be
+     * {@link IOUtil#copyCharacter(java.io.Reader, java.io.Writer) read}.
+     * </ul>
+     * </ol>
+     * </ol>
+     * 
+     * @since 4.0
+     */
+    public ExtendedDataInputStream getLobs();
+
+    /**
+     * Returns an unmodifiable map from all temporary IDs to their persistent counter parts.
+     */
+    public Map<CDOID, CDOID> getIDMappings();
+
+    /**
+     * @since 4.0
+     */
+    public CDOCommitInfo createCommitInfo();
+
+    /**
+     * @since 3.0
+     */
+    public String getRollbackMessage();
+
+    /**
+     * @since 4.0
+     */
+    public List<CDOIDReference> getXRefs();
+
+    /**
+     * @since 4.1
+     */
+    public List<LockState<Object, IView>> getPostCommmitLockStates();
+  }
+
+  /**
+   * @author Eike Stepper
+   * @since 2.0
+   * @noimplement This interface is not intended to be implemented by clients.
+   * @apiviz.exclude
+   */
+  public interface QueryResourcesContext extends CDOBranchPoint
+  {
+    public CDOID getFolderID();
+
+    public String getName();
+
+    public boolean exactMatch();
+
+    /**
+     * Returns the maximum number of results expected by the client or {@link CDOQueryInfo#UNLIMITED_RESULTS} for no
+     * limitation.
+     */
+    public int getMaxResults();
+
+    /**
+     * Adds the CDOID of one resource to the results of the underlying query.
+     * 
+     * @return <code>true</code> to indicate that more results can be passed subsequently, <code>false</code> otherwise
+     *         (i.e. maxResults has been reached or an asynchronous query has been canceled).
+     */
+    public boolean addResource(CDOID resourceID);
+
+    /**
+     * @author Eike Stepper
+     * @since 2.0
+     * @apiviz.exclude
+     */
+    public interface ExactMatch extends QueryResourcesContext
+    {
+      public CDOID getResourceID();
+    }
+  }
+
+  /**
+   * @author Eike Stepper
+   * @since 3.0
+   * @noimplement This interface is not intended to be implemented by clients.
+   * @apiviz.exclude
+   */
+  public interface QueryXRefsContext extends CDOBranchPoint
+  {
+    /**
+     * @since 4.0
+     */
+    public Map<CDOID, EClass> getTargetObjects();
+
+    public EReference[] getSourceReferences();
+
+    /**
+     * @since 4.0
+     */
+    public Map<EClass, List<EReference>> getSourceCandidates();
+
+    /**
+     * Returns the maximum number of results expected by the client or {@link CDOQueryInfo#UNLIMITED_RESULTS} for no
+     * limitation.
+     */
+    public int getMaxResults();
+
+    /**
+     * Adds the data of one cross reference to the results of the underlying query.
+     * 
+     * @return <code>true</code> to indicate that more results can be passed subsequently, <code>false</code> otherwise
+     *         (i.e. maxResults has been reached or an asynchronous query has been canceled).
+     */
+    public boolean addXRef(CDOID targetID, CDOID sourceID, EReference sourceReference, int sourceIndex);
+  }
+
+  /**
+   * @author Eike Stepper
+   * @since 4.0
+   * @apiviz.exclude
+   */
+  public interface Raw extends IStoreAccessor
+  {
+    /**
+     * Serializes all backend data within the given ranges such that it can be deserialized by the
+     * {@link #rawImport(CDODataInput, int, int, long, long, OMMonitor) rawImport()} method of a different instance of
+     * the same implementation of {@link IStoreAccessor.Raw raw store accessor}.
+     * <p>
+     * <b>Implementation note:</b> The implementor of this method is free to choose a serialization format as it only
+     * needs to be understood by different instances of the same implementation of {@link IStoreAccessor.Raw raw store
+     * accessor}.
+     * <p>
+     * <b>Usage context:</b> This method is only called in the context of a
+     * {@link CDOProtocolConstants#SIGNAL_REPLICATE_REPOSITORY_RAW REPLICATE_REPOSITORY_RAW} signal that is triggered
+     * from {@link IRepositorySynchronizer}.
+     * 
+     * @param out
+     *          the <i>stream</i> to serialize the data to.
+     * @param fromBranchID
+     *          the {@link CDOBranch#getID() ID} of the first branch to be exported.
+     * @param toBranchID
+     *          the {@link CDOBranch#getID() ID} of the last branch to be exported.
+     * @param fromCommitTime
+     *          the first {@link CDOBranchPoint#getTimeStamp() time stamp} of all non-branch data (e.g.
+     *          {@link CDORevision revisions}, {@link CDOCommitInfo commit infos}, {@link CDOPackageUnit package units},
+     *          etc...) to be exported.
+     * @param toCommitTime
+     *          the last {@link CDOBranchPoint#getTimeStamp() time stamp} of all non-branch data (e.g.
+     *          {@link CDORevision revisions}, {@link CDOCommitInfo commit infos}, {@link CDOPackageUnit package units},
+     *          etc...) to be exported.
+     * @throws IOException
+     *           if the <i>stream</i> could not be written to.
+     * @throws UnsupportedOperationException
+     *           if this {@link IStoreAccessor.Raw raw store accessor} does not support branching.
+     */
+    public void rawExport(CDODataOutput out, int fromBranchID, int toBranchID, long fromCommitTime, long toCommitTime)
+        throws IOException;
+
+    /**
+     * Deserializes backend data that has been serialized by the {@link #rawExport(CDODataOutput, int, int, long, long)
+     * rawExport()} method of a different instance of the same implementation of {@link IStoreAccessor.Raw raw store
+     * accessor}.
+     * <p>
+     * <b>Implementation note:</b> The implementor of this method is free to choose a serialization format as it only
+     * needs to be understood by different instances of the same implementation of {@link IStoreAccessor.Raw raw store
+     * accessor}.
+     * <p>
+     * <b>Usage context:</b> This method is only called in the context of a
+     * {@link CDOProtocolConstants#SIGNAL_REPLICATE_REPOSITORY_RAW REPLICATE_REPOSITORY_RAW} signal that is triggered
+     * from {@link IRepositorySynchronizer}.
+     * 
+     * @param in
+     *          the <i>stream</i> to deserialize the data from.
+     * @param fromBranchID
+     *          the {@link CDOBranch#getID() ID} of the first branch to be imported.
+     * @param toBranchID
+     *          the {@link CDOBranch#getID() ID} of the last branch to be imported.
+     * @param fromCommitTime
+     *          the first {@link CDOBranchPoint#getTimeStamp() time stamp} of all non-branch data (e.g.
+     *          {@link CDORevision revisions}, {@link CDOCommitInfo commit infos}, {@link CDOPackageUnit package units},
+     *          etc...) to be imported.
+     * @param toCommitTime
+     *          the last {@link CDOBranchPoint#getTimeStamp() time stamp} of all non-branch data (e.g.
+     *          {@link CDORevision revisions}, {@link CDOCommitInfo commit infos}, {@link CDOPackageUnit package units},
+     *          etc...) to be imported.
+     * @throws IOException
+     *           if the <i>stream</i> could not be read from.
+     * @throws UnsupportedOperationException
+     *           if this {@link IStoreAccessor.Raw raw store accessor} does not support branching.
+     */
+    public void rawImport(CDODataInput in, int fromBranchID, int toBranchID, long fromCommitTime, long toCommitTime,
+        OMMonitor monitor) throws IOException;
+
+    /**
+     * Stores the given {@link CDOPackageUnit package units} in the backend represented by this
+     * {@link IStoreAccessor.Raw raw store accessor} without going through a regular
+     * {@link IStoreAccessor #commit(OMMonitor) commit}. A regular commit operation would assign new
+     * {@link CDOPackageUnit#getTimeStamp() time stamps}, which is not desired in the context of a replication
+     * operation.
+     * <p>
+     * <b>Implementation note:</b> The implementor of this method may rely on the fact that multiple subsequent calls to
+     * this method are followed by a single final call to the {@link #rawCommit(double, OMMonitor) rawCommit()} method
+     * where the accumulated backend changes can be committed atomically.
+     * 
+     * @param packageUnits
+     *          the package units to be stored in the backend represented by this {@link IStoreAccessor.Raw raw store
+     *          accessor}.
+     * @param monitor
+     *          a progress monitor that <b>may be</b> used to report proper progress of this operation to the caller and
+     *          <b>may be</b> used to react to cancelation requests of the caller and <b>must be</b> touched regularly
+     *          to prevent timeouts from expiring in the caller.
+     * @see #rawCommit(double, OMMonitor)
+     */
+    public void rawStore(InternalCDOPackageUnit[] packageUnits, OMMonitor monitor);
+
+    /**
+     * Stores the given {@link CDORevision revision} in the backend represented by this {@link IStoreAccessor.Raw raw
+     * store accessor} without going through a regular {@link IStoreAccessor#commit(OMMonitor) commit}. A regular commit
+     * operation would assign new {@link CDORevisionKey#getID() IDs} and {@link CDOBranchPoint#getTimeStamp() time
+     * stamps}, which is not desired in the context of a replication operation.
+     * <p>
+     * <b>Implementation note:</b> The implementor of this method may rely on the fact that multiple subsequent calls to
+     * this method are followed by a single final call to the {@link #rawCommit(double, OMMonitor) rawCommit()} method
+     * where the accumulated backend changes can be committed atomically.
+     * 
+     * @param revision
+     *          the revision to be stored in the backend represented by this {@link IStoreAccessor.Raw raw store
+     *          accessor}.
+     * @param monitor
+     *          a progress monitor that <b>may be</b> used to report proper progress of this operation to the caller and
+     *          <b>may be</b> used to react to cancelation requests of the caller and <b>must be</b> touched regularly
+     *          to prevent timeouts from expiring in the caller.
+     * @see #rawCommit(double, OMMonitor)
+     */
+    public void rawStore(InternalCDORevision revision, OMMonitor monitor);
+
+    /**
+     * Stores the given {@link CDOBlob blob} in the backend represented by this {@link IStoreAccessor.Raw raw store
+     * accessor} without going through a regular {@link IStoreAccessor#commit(OMMonitor) commit}.
+     * <p>
+     * <b>Implementation note:</b> The implementor of this method may rely on the fact that multiple subsequent calls to
+     * this method are followed by a single final call to the {@link #rawCommit(double, OMMonitor) rawCommit()} method
+     * where the accumulated backend changes can be committed atomically.
+     * 
+     * @param id
+     *          the {@link CDOBlob#getID() ID} of the blob to be stored in the backend represented by this
+     *          {@link IStoreAccessor.Raw raw store accessor}.
+     * @param size
+     *          the {@link CDOBlob#getSize() size} of the blob to be stored in the backend represented by this
+     *          {@link IStoreAccessor.Raw raw store accessor}.
+     * @param inputStream
+     *          the {@link CDOBlob#getContents() contents} of the blob to be stored in the backend represented by this
+     *          {@link IStoreAccessor.Raw raw store accessor}.
+     * @see #rawCommit(double, OMMonitor)
+     */
+    public void rawStore(byte[] id, long size, InputStream inputStream) throws IOException;
+
+    /**
+     * Stores the given {@link CDOClob clob} in the backend represented by this {@link IStoreAccessor.Raw raw store
+     * accessor} without going through a regular {@link IStoreAccessor#commit(OMMonitor) commit}.
+     * <p>
+     * <b>Implementation note:</b> The implementor of this method may rely on the fact that multiple subsequent calls to
+     * this method are followed by a single final call to the {@link #rawCommit(double, OMMonitor) rawCommit()} method
+     * where the accumulated backend changes can be committed atomically.
+     * 
+     * @param id
+     *          the {@link CDOClob#getID() ID} of the clob to be stored in the backend represented by this
+     *          {@link IStoreAccessor.Raw raw store accessor}.
+     * @param size
+     *          the {@link CDOClob#getSize() size} of the clob to be stored in the backend represented by this
+     *          {@link IStoreAccessor.Raw raw store accessor}.
+     * @param reader
+     *          the {@link CDOClob#getContents() contents} of the clob to be stored in the backend represented by this
+     *          {@link IStoreAccessor.Raw raw store accessor}.
+     * @see #rawCommit(double, OMMonitor)
+     */
+    public void rawStore(byte[] id, long size, Reader reader) throws IOException;
+
+    /**
+     * Stores the given {@link CDOCommitInfo commit} in the backend represented by this {@link IStoreAccessor.Raw raw
+     * store accessor} without going through a regular {@link IStoreAccessor#commit(OMMonitor) commit}.
+     * <p>
+     * <b>Implementation note:</b> The implementor of this method may rely on the fact that multiple subsequent calls to
+     * this method are followed by a single final call to the {@link #rawCommit(double, OMMonitor) rawCommit()} method
+     * where the accumulated backend changes can be committed atomically.
+     * 
+     * @param branch
+     *          the {@link CDOCommitInfo#getBranch() branch} of the commit info to be stored in the backend represented
+     *          by this {@link IStoreAccessor.Raw raw store accessor}.
+     * @param timeStamp
+     *          the {@link CDOCommitInfo#getTimeStamp() time stamp} of the commit info to be stored in the backend
+     *          represented by this {@link IStoreAccessor.Raw raw store accessor}.
+     * @param previousTimeStamp
+     *          the {@link CDOCommitInfo#getPreviousTimeStamp() previous time stamp} of the commit info to be stored in
+     *          the backend represented by this {@link IStoreAccessor.Raw raw store accessor}.
+     * @param userID
+     *          the {@link CDOCommitInfo#getUserID() user ID} of the commit info to be stored in the backend represented
+     *          by this {@link IStoreAccessor.Raw raw store accessor}.
+     * @param comment
+     *          the {@link CDOCommitInfo#getComment() comment} of the commit info to be stored in the backend
+     *          represented by this {@link IStoreAccessor.Raw raw store accessor}.
+     * @see #rawCommit(double, OMMonitor)
+     */
+    public void rawStore(CDOBranch branch, long timeStamp, long previousTimeStamp, String userID, String comment,
+        OMMonitor monitor);
+
+    /**
+     * Deletes the revision identified by the given {@link CDORevisionKey key} from the backend represented by this
+     * {@link IStoreAccessor.Raw raw store accessor} without going through a regular
+     * {@link IStoreAccessor#commit(OMMonitor) commit}.
+     * <p>
+     * <b>Implementation note:</b> The implementor of this method may rely on the fact that multiple subsequent calls to
+     * this method are followed by a single final call to the {@link #rawCommit(double, OMMonitor) rawCommit()} method
+     * where the accumulated backend changes can be committed atomically.
+     * 
+     * @see #rawCommit(double, OMMonitor)
+     * @deprecated Not used anymore
+     */
+    @Deprecated
+    public void rawDelete(CDOID id, int version, CDOBranch branch, EClass eClass, OMMonitor monitor);
+
+    /**
+     * Atomically commits the accumulated backend changes resulting from previous calls to the rawStore() methods.
+     * 
+     * @param commitWork
+     *          the amount of work to use up from the monitor while executing the commit.
+     * @param monitor
+     *          a progress monitor that <b>may be</b> used to report proper progress of this operation to the caller and
+     *          <b>may be</b> used to react to cancelation requests of the caller and <b>must be</b> touched regularly
+     *          to prevent timeouts from expiring in the caller.
+     * @see #rawStore(InternalCDOPackageUnit[], OMMonitor)
+     * @see #rawStore(InternalCDORevision, OMMonitor)
+     * @see #rawStore(byte[], long, InputStream)
+     * @see #rawStore(byte[], long, Reader)
+     * @see #rawStore(CDOBranch, long, long, String, String, OMMonitor)
+     */
+    public void rawCommit(double commitWork, OMMonitor monitor);
+  }
+
+  /**
+   * @author Eike Stepper
+   * @since 4.0
+   * @apiviz.exclude
+   */
+  public interface DurableLocking extends IDurableLockingManager
+  {
+    public void lock(String durableLockingID, LockType type, Collection<? extends Object> objectsToLock);
+
+    public void unlock(String durableLockingID, LockType type, Collection<? extends Object> objectsToUnlock);
+
+    public void unlock(String durableLockingID);
+  }
+
+  /**
+   * @author Caspar De Groot
+   * @since 4.1
+   * @apiviz.exclude
+   */
+  public interface DurableLocking2 extends DurableLocking
+  {
+    LockArea createLockArea(String durableLockingID, String userID, CDOBranchPoint branchPoint, boolean readOnly,
+        Map<CDOID, LockGrade> locks);
+
+    public void updateLockArea(LockArea lockArea);
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IStoreChunkReader.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IStoreChunkReader.java
new file mode 100644
index 0000000..a27d25f
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IStoreChunkReader.java
@@ -0,0 +1,119 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Simon McDuff - bug 210868
+ */
+package org.eclipse.emf.cdo.server;
+
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+import java.util.List;
+
+/**
+ * @author Eike Stepper
+ * @apiviz.uses {@link IStoreChunkReader.Chunk} - - reads
+ */
+public interface IStoreChunkReader
+{
+  /**
+   * @since 2.0
+   */
+  public IStoreAccessor getAccessor();
+
+  public CDORevision getRevision();
+
+  /**
+   * @since 2.0
+   */
+  public EStructuralFeature getFeature();
+
+  public void addSimpleChunk(int index);
+
+  /**
+   * @param fromIndex
+   *          Inclusive value.
+   * @param toIndex
+   *          Exclusive value.
+   */
+  public void addRangedChunk(int fromIndex, int toIndex);
+
+  public List<Chunk> executeRead();
+
+  /**
+   * @author Eike Stepper
+   */
+  public static class Chunk
+  {
+    private int startIndex;
+
+    private Object ids;
+
+    public Chunk(int startIndex)
+    {
+      this.startIndex = startIndex;
+    }
+
+    public Chunk(int startIndex, int size)
+    {
+      this(startIndex);
+      ids = new Object[size];
+    }
+
+    public int getStartIndex()
+    {
+      return startIndex;
+    }
+
+    public int size()
+    {
+      return ids instanceof Object[] ? ((Object[])ids).length : 1;
+    }
+
+    /**
+     * @since 2.0
+     */
+    public Object get(int indexInChunk)
+    {
+      if (ids instanceof Object[])
+      {
+        return ((Object[])ids)[indexInChunk];
+      }
+
+      if (indexInChunk == 0)
+      {
+        return ids;
+      }
+
+      throw new ArrayIndexOutOfBoundsException(indexInChunk);
+    }
+
+    /**
+     * @since 2.0
+     */
+    public void add(int indexInChunk, Object value)
+    {
+      if (ids instanceof Object[])
+      {
+        ((Object[])ids)[indexInChunk] = value;
+      }
+      else
+      {
+        if (indexInChunk == 0)
+        {
+          ids = value;
+          return;
+        }
+
+        throw new ArrayIndexOutOfBoundsException(indexInChunk);
+      }
+    }
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IStoreFactory.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IStoreFactory.java
new file mode 100644
index 0000000..daaa452
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IStoreFactory.java
@@ -0,0 +1,29 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server;
+
+import org.w3c.dom.Element;
+
+import java.util.Map;
+
+/**
+ * @author Eike Stepper
+ * @apiviz.uses {@link IStore} - - creates
+ */
+public interface IStoreFactory
+{
+  public String getStoreType();
+
+  /**
+   * @since 4.0
+   */
+  public IStore createStore(String repositoryName, Map<String, String> repositoryProperties, Element storeConfig);
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/ISynchronizableRepository.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/ISynchronizableRepository.java
new file mode 100644
index 0000000..c692607
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/ISynchronizableRepository.java
@@ -0,0 +1,43 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server;
+
+/**
+ * A repository with the ability to {@link IRepositorySynchronizer synchronize} its content with another repository.
+ * 
+ * @author Eike Stepper
+ * @since 3.0
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ * @apiviz.landmark
+ * @apiviz.has {@link IRepositorySynchronizer}
+ * @apiviz.has {@link ISession} oneway - - replicatorSession
+ */
+public interface ISynchronizableRepository extends IRepository
+{
+  public IRepositorySynchronizer getSynchronizer();
+
+  public ISession getReplicatorSession();
+
+  public int getLastReplicatedBranchID();
+
+  public long getLastReplicatedCommitTime();
+
+  /**
+   * @since 4.1
+   */
+  public void goOnline();
+
+  /**
+   * @since 4.1
+   */
+  public void goOffline();
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/ITransaction.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/ITransaction.java
new file mode 100644
index 0000000..021d214
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/ITransaction.java
@@ -0,0 +1,24 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Simon McDuff - bug 213402
+ */
+package org.eclipse.emf.cdo.server;
+
+import org.eclipse.emf.cdo.common.CDOCommonTransaction;
+
+/**
+ * @author Eike Stepper
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ * @apiviz.landmark
+ */
+public interface ITransaction extends IView, CDOCommonTransaction
+{
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IView.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IView.java
new file mode 100644
index 0000000..dc5eea3
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IView.java
@@ -0,0 +1,29 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server;
+
+import org.eclipse.emf.cdo.common.CDOCommonView;
+
+/**
+ * @author Eike Stepper
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ * @apiviz.landmark
+ */
+public interface IView extends CDOCommonView
+{
+  /**
+   * @since 2.0
+   */
+  public IRepository getRepository();
+
+  public ISession getSession();
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/RepositoryNotFoundException.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/RepositoryNotFoundException.java
new file mode 100644
index 0000000..bce4b76
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/RepositoryNotFoundException.java
@@ -0,0 +1,37 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server;
+
+import org.eclipse.emf.cdo.common.util.CDOException;
+
+/**
+ * @author Eike Stepper
+ */
+public class RepositoryNotFoundException extends CDOException
+{
+  private static final long serialVersionUID = 1L;
+
+  public RepositoryNotFoundException(String repositoryName)
+  {
+    super(repositoryName);
+  }
+
+  public String getRepositoryName()
+  {
+    return super.getMessage();
+  }
+
+  @Override
+  public String getMessage()
+  {
+    return "Repository not found: " + getRepositoryName(); //$NON-NLS-1$
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/StoreThreadLocal.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/StoreThreadLocal.java
new file mode 100644
index 0000000..dd0ac05
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/StoreThreadLocal.java
@@ -0,0 +1,118 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server;
+
+import org.eclipse.emf.cdo.spi.server.InternalSession;
+
+import org.eclipse.net4j.util.lifecycle.LifecycleUtil;
+
+/**
+ * @author Eike Stepper
+ * @since 2.0
+ * @apiviz.exclude
+ */
+public final class StoreThreadLocal
+{
+  private static final ThreadLocal<InternalSession> SESSION = new InheritableThreadLocal<InternalSession>();
+
+  private static final ThreadLocal<IStoreAccessor> ACCESSOR = new InheritableThreadLocal<IStoreAccessor>();
+
+  private static final ThreadLocal<IStoreAccessor.CommitContext> COMMIT_CONTEXT = new InheritableThreadLocal<IStoreAccessor.CommitContext>();
+
+  private StoreThreadLocal()
+  {
+  }
+
+  /**
+   * @since 3.0
+   */
+  public static void setSession(InternalSession session)
+  {
+    SESSION.set(session);
+    ACCESSOR.set(null);
+  }
+
+  /**
+   * Returns the session associated with the current thread.
+   * 
+   * @return Never <code>null</code>.
+   * @throws IllegalStateException
+   *           if no session is associated with the current thread.
+   * @since 3.0
+   */
+  public static InternalSession getSession()
+  {
+    InternalSession session = SESSION.get();
+    if (session == null)
+    {
+      throw new IllegalStateException("session == null"); //$NON-NLS-1$
+    }
+
+    return session;
+  }
+
+  public static void setAccessor(IStoreAccessor accessor)
+  {
+    // IStoreAccessor old = ACCESSOR.get();
+    // if (old != null && old != accessor)
+    // {
+    // throw new IllegalStateException("Attempt to overwrite accessor");
+    // }
+
+    SESSION.set(accessor == null ? null : accessor.getSession());
+    ACCESSOR.set(accessor);
+  }
+
+  public static IStoreAccessor getAccessor()
+  {
+    IStoreAccessor accessor = ACCESSOR.get();
+    if (accessor == null)
+    {
+      ISession session = getSession();
+      IStore store = session.getManager().getRepository().getStore();
+      accessor = store.getReader(session);
+      ACCESSOR.set(accessor);
+    }
+
+    return accessor;
+  }
+
+  public static void setCommitContext(IStoreAccessor.CommitContext commitContext)
+  {
+    COMMIT_CONTEXT.set(commitContext);
+  }
+
+  public static IStoreAccessor.CommitContext getCommitContext()
+  {
+    return COMMIT_CONTEXT.get();
+  }
+
+  public static void release()
+  {
+    try
+    {
+      IStoreAccessor accessor = ACCESSOR.get();
+      if (accessor != null)
+      {
+        if (LifecycleUtil.isActive(accessor))
+        {
+          accessor.release();
+        }
+      }
+    }
+    finally
+    {
+      ACCESSOR.set(null);
+      SESSION.set(null);
+      COMMIT_CONTEXT.set(null);
+    }
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/embedded/CDOSession.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/embedded/CDOSession.java
new file mode 100644
index 0000000..9d68ad8
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/embedded/CDOSession.java
@@ -0,0 +1,21 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server.embedded;
+
+/**
+ * @author Eike Stepper
+ * @since 3.0
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface CDOSession extends org.eclipse.emf.cdo.session.CDOSession
+{
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/embedded/CDOSessionConfiguration.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/embedded/CDOSessionConfiguration.java
new file mode 100644
index 0000000..4481992
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/embedded/CDOSessionConfiguration.java
@@ -0,0 +1,33 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server.embedded;
+
+import org.eclipse.emf.cdo.common.revision.CDORevisionManager;
+import org.eclipse.emf.cdo.server.IRepository;
+
+/**
+ * @author Eike Stepper
+ * @since 3.0
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface CDOSessionConfiguration extends org.eclipse.emf.cdo.session.CDOSessionConfiguration
+{
+  public IRepository getRepository();
+
+  public void setRepository(IRepository repository);
+
+  public CDORevisionManager getRevisionManager();
+
+  public void setRevisionManager(CDORevisionManager revisionManager);
+
+  public org.eclipse.emf.cdo.server.embedded.CDOSession openSession();
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/embedded/package-info.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/embedded/package-info.java
new file mode 100644
index 0000000..e4b6b8e
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/embedded/package-info.java
@@ -0,0 +1,15 @@
+/*

+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ * 

+ * Contributors:

+ *    Eike Stepper - initial API and implementation

+ */

+

+/**

+ * Server concepts for dealing with embedded sessions.

+ */

+package org.eclipse.emf.cdo.server.embedded;

diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/mem/IMEMStore.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/mem/IMEMStore.java
new file mode 100644
index 0000000..ef73bbd
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/mem/IMEMStore.java
@@ -0,0 +1,56 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server.mem;
+
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.revision.CDOAllRevisionsProvider;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.server.IStore;
+import org.eclipse.emf.cdo.server.IStore.CanHandleClientAssignedIDs;
+
+import org.eclipse.net4j.util.lifecycle.LifecycleUtil;
+
+import org.eclipse.emf.ecore.EClass;
+
+/**
+ * A simple in-memory store.
+ * 
+ * @author Eike Stepper
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ * @since 4.0
+ */
+public interface IMEMStore extends IStore, CDOAllRevisionsProvider, CanHandleClientAssignedIDs
+{
+  public static final int UNLIMITED = -1;
+
+  /**
+   * Returns the number of {@link CDORevision revisions} per {@link CDOID} that are stored.
+   */
+  public int getListLimit();
+
+  /**
+   * Limits the number of {@link CDORevision revisions} per {@link CDOID} to the given value.
+   * <p>
+   * A value of 2, for example, stores the current and the immediately preceding revisions whereas older revisions are
+   * dropped from thids store. A value of 1 only stores the current revisions. A value of {@link #UNLIMITED} does not
+   * limit the number of revisions to be stored for any id.
+   * <p>
+   * The list limit can be set and enforced at any time before or after the {@link LifecycleUtil#activate(Object)
+   * activation} of this store.
+   */
+  public void setListLimit(int listLimit);
+
+  /**
+   * @since 3.0
+   */
+  public EClass getObjectType(CDOID id);
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/mem/MEMStoreUtil.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/mem/MEMStoreUtil.java
new file mode 100644
index 0000000..358a29d
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/mem/MEMStoreUtil.java
@@ -0,0 +1,32 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.server.mem;
+
+import org.eclipse.emf.cdo.internal.server.mem.MEMStore;
+
+/**
+ * @author Eike Stepper
+ * @since 2.0
+ */
+public final class MEMStoreUtil
+{
+  private MEMStoreUtil()
+  {
+  }
+
+  /**
+   * @since 4.0
+   */
+  public static IMEMStore createMEMStore()
+  {
+    return new MEMStore();
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/mem/package-info.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/mem/package-info.java
new file mode 100644
index 0000000..d6b7539
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/mem/package-info.java
@@ -0,0 +1,15 @@
+/*

+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ * 

+ * Contributors:

+ *    Eike Stepper - initial API and implementation

+ */

+

+/**

+ * Server concepts for dealing with in-memory stores.

+ */

+package org.eclipse.emf.cdo.server.mem;

diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/package-info.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/package-info.java
new file mode 100644
index 0000000..af751e4
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/package-info.java
@@ -0,0 +1,23 @@
+/*

+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ * 

+ * Contributors:

+ *    Eike Stepper - initial API and implementation

+ */

+

+/**

+ * Server concepts for dealing with repositories and stores.

+ * 

+ * @apiviz.exclude .*\.CDOServerBrowser.*

+ * @apiviz.exclude .*\.CommitInfoLoader

+ * @apiviz.exclude .*\.BranchLoader

+ * @apiviz.exclude .*\.IContainer

+ * @apiviz.exclude .*\.INotifier

+ * @apiviz.exclude .*Exception

+ */

+package org.eclipse.emf.cdo.server;

+

diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/ContainerQueryHandlerProvider.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/ContainerQueryHandlerProvider.java
new file mode 100644
index 0000000..3d44fe9
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/ContainerQueryHandlerProvider.java
@@ -0,0 +1,44 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.spi.server;
+
+import org.eclipse.emf.cdo.common.util.CDOQueryInfo;
+import org.eclipse.emf.cdo.server.IQueryHandler;
+import org.eclipse.emf.cdo.server.IQueryHandlerProvider;
+
+import org.eclipse.net4j.util.container.IManagedContainer;
+
+/**
+ * @author Eike Stepper
+ * @since 2.0
+ */
+public class ContainerQueryHandlerProvider implements IQueryHandlerProvider
+{
+  private IManagedContainer container;
+
+  public ContainerQueryHandlerProvider(IManagedContainer container)
+  {
+    this.container = container;
+  }
+
+  public IManagedContainer getContainer()
+  {
+    return container;
+  }
+
+  /**
+   * @since 3.0
+   */
+  public IQueryHandler getQueryHandler(CDOQueryInfo info)
+  {
+    return (IQueryHandler)container.getElement(QueryHandlerFactory.PRODUCT_GROUP, info.getQueryLanguage(), null);
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/ContainerRepositoryProvider.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/ContainerRepositoryProvider.java
new file mode 100644
index 0000000..5323ff8
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/ContainerRepositoryProvider.java
@@ -0,0 +1,49 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.spi.server;
+
+import org.eclipse.emf.cdo.internal.server.bundle.OM;
+import org.eclipse.emf.cdo.server.IRepository;
+import org.eclipse.emf.cdo.server.IRepositoryProvider;
+
+import org.eclipse.net4j.util.container.IManagedContainer;
+
+/**
+ * @author Eike Stepper
+ * @since 2.0
+ */
+public class ContainerRepositoryProvider implements IRepositoryProvider
+{
+  private IManagedContainer container;
+
+  public ContainerRepositoryProvider(IManagedContainer container)
+  {
+    this.container = container;
+  }
+
+  public IManagedContainer getContainer()
+  {
+    return container;
+  }
+
+  public IRepository getRepository(String name)
+  {
+    try
+    {
+      return RepositoryFactory.get(container, name);
+    }
+    catch (Exception ex)
+    {
+      OM.LOG.error(ex);
+      return null;
+    }
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/DurableLockArea.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/DurableLockArea.java
new file mode 100644
index 0000000..40c3826
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/DurableLockArea.java
@@ -0,0 +1,108 @@
+/**

+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ * 

+ * Contributors:

+ *    Eike Stepper - initial API and implementation

+ */

+package org.eclipse.emf.cdo.spi.server;

+

+import org.eclipse.emf.cdo.common.branch.CDOBranch;

+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;

+import org.eclipse.emf.cdo.common.id.CDOID;

+import org.eclipse.emf.cdo.common.lock.CDOLockUtil;

+import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockArea;

+import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockGrade;

+

+import java.text.MessageFormat;

+import java.util.Map;

+

+/**

+ * @author Eike Stepper

+ * @since 4.0

+ * @noextend This interface is not intended to be extended by clients.

+ * @deprecated Use {@link CDOLockUtil#createLockArea(String, String, CDOBranchPoint, boolean, Map)} instead

+ */

+@Deprecated

+public class DurableLockArea implements LockArea

+{

+  public static final int DEFAULT_DURABLE_LOCKING_ID_BYTES = 32;

+

+  private String durableLockingID;

+

+  private String userID;

+

+  private CDOBranchPoint branchPoint;

+

+  private boolean readOnly;

+

+  private Map<CDOID, LockGrade> locks;

+

+  public DurableLockArea(String durableLockingID, String userID, CDOBranchPoint branchPoint, boolean readOnly,

+      Map<CDOID, LockGrade> locks)

+  {

+    this.durableLockingID = durableLockingID;

+    this.userID = userID;

+    this.branchPoint = branchPoint;

+    this.readOnly = readOnly;

+    this.locks = locks;

+  }

+

+  public String getDurableLockingID()

+  {

+    return durableLockingID;

+  }

+

+  public String getUserID()

+  {

+    return userID;

+  }

+

+  public CDOBranch getBranch()

+  {

+    return branchPoint.getBranch();

+  }

+

+  public long getTimeStamp()

+  {

+    return branchPoint.getTimeStamp();

+  }

+

+  public boolean isReadOnly()

+  {

+    return readOnly;

+  }

+

+  public Map<CDOID, LockGrade> getLocks()

+  {

+    return locks;

+  }

+

+  @Override

+  public String toString()

+  {

+    return MessageFormat.format("DurableLockArea\nid={0}\nuser={1}\nbranchPoint={2}\nreadOnly={3}\nlocks={4}",

+        durableLockingID, userID, branchPoint, readOnly, locks);

+  }

+

+  public static String createDurableLockingID()

+  {

+    return CDOLockUtil.createDurableLockingID();

+  }

+

+  public static String createDurableLockingID(int bytes)

+  {

+    return CDOLockUtil.createDurableLockingID(bytes);

+  }

+

+  /**

+   * @since 4.1

+   */

+  public boolean isMissing()

+  {

+    return false;

+  }

+}

diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/FactoriesQueryHandlerProvider.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/FactoriesQueryHandlerProvider.java
new file mode 100644
index 0000000..19f7a2b
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/FactoriesQueryHandlerProvider.java
@@ -0,0 +1,76 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.spi.server;
+
+import org.eclipse.emf.cdo.common.util.CDOQueryInfo;
+import org.eclipse.emf.cdo.server.IQueryHandler;
+import org.eclipse.emf.cdo.server.IQueryHandlerProvider;
+
+import org.eclipse.net4j.util.factory.IFactory;
+import org.eclipse.net4j.util.registry.HashMapRegistry;
+import org.eclipse.net4j.util.registry.IRegistry;
+
+/**
+ * @author Eike Stepper
+ * @since 2.0
+ */
+public class FactoriesQueryHandlerProvider implements IQueryHandlerProvider
+{
+  private IRegistry<String, IFactory> registry;
+
+  public FactoriesQueryHandlerProvider()
+  {
+  }
+
+  public FactoriesQueryHandlerProvider(IRegistry<String, IFactory> registry)
+  {
+    setRegistry(registry);
+  }
+
+  public FactoriesQueryHandlerProvider(IFactory factory)
+  {
+    addFactory(factory);
+  }
+
+  public IRegistry<String, IFactory> getRegistry()
+  {
+    if (registry == null)
+    {
+      registry = new HashMapRegistry<String, IFactory>();
+    }
+
+    return registry;
+  }
+
+  public void setRegistry(IRegistry<String, IFactory> registry)
+  {
+    this.registry = registry;
+  }
+
+  public void addFactory(IFactory factory)
+  {
+    getRegistry().put(factory.getKey().getType(), factory);
+  }
+
+  /**
+   * @since 3.0
+   */
+  public IQueryHandler getQueryHandler(CDOQueryInfo info)
+  {
+    IFactory factory = registry.get(info.getQueryLanguage());
+    if (factory != null)
+    {
+      return (IQueryHandler)factory.create(null);
+    }
+
+    return null;
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/IAppExtension.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/IAppExtension.java
new file mode 100644
index 0000000..b828bd1
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/IAppExtension.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.spi.server;
+
+import java.io.File;
+
+/**
+ * @author Eike Stepper
+ * @since 3.0
+ */
+public interface IAppExtension
+{
+  public static final String EXT_POINT = "appExtensions"; //$NON-NLS-1$
+
+  public void start(File configFile) throws Exception;
+
+  public void stop() throws Exception;
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/ISessionProtocol.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/ISessionProtocol.java
new file mode 100644
index 0000000..1562ae0
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/ISessionProtocol.java
@@ -0,0 +1,63 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.spi.server;
+
+import org.eclipse.emf.cdo.common.CDOCommonRepository;
+import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
+import org.eclipse.emf.cdo.common.protocol.CDOProtocol;
+import org.eclipse.emf.cdo.session.remote.CDORemoteSessionMessage;
+import org.eclipse.emf.cdo.spi.common.CDOAuthenticationResult;
+import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranch;
+
+/**
+ * @author Eike Stepper
+ * @since 3.0
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface ISessionProtocol extends CDOProtocol
+{
+  /**
+   * @since 4.0
+   */
+  public CDOAuthenticationResult sendAuthenticationChallenge(byte[] randomToken) throws Exception;
+
+  public void sendRepositoryTypeNotification(CDOCommonRepository.Type oldType, CDOCommonRepository.Type newType)
+      throws Exception;
+
+  /**
+   * @deprecated
+   */
+  @Deprecated
+  public void sendRepositoryStateNotification(CDOCommonRepository.State oldState, CDOCommonRepository.State newState)
+      throws Exception;
+
+  /**
+   * @since 4.1
+   */
+  public void sendRepositoryStateNotification(CDOCommonRepository.State oldState, CDOCommonRepository.State newState,
+      CDOID rootResourceID) throws Exception;
+
+  public void sendBranchNotification(InternalCDOBranch branch) throws Exception;
+
+  public void sendCommitNotification(CDOCommitInfo commitInfo) throws Exception;
+
+  public void sendRemoteSessionNotification(InternalSession sender, byte opcode) throws Exception;
+
+  public void sendRemoteMessageNotification(InternalSession sender, CDORemoteSessionMessage message) throws Exception;
+
+  /**
+   * @since 4.1
+   */
+  public void sendLockNotification(CDOLockChangeInfo lockChangeInfo) throws Exception;
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalCommitContext.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalCommitContext.java
new file mode 100644
index 0000000..135b6b4
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalCommitContext.java
@@ -0,0 +1,103 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.spi.server;
+
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.server.IStoreAccessor;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionDelta;
+
+import org.eclipse.net4j.util.io.ExtendedDataInputStream;
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+import org.eclipse.net4j.util.om.monitor.ProgressDistributable;
+import org.eclipse.net4j.util.om.monitor.ProgressDistributor;
+
+import org.eclipse.emf.ecore.EClass;
+
+import java.util.Map;
+
+/**
+ * @author Eike Stepper
+ * @since 3.0
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface InternalCommitContext extends IStoreAccessor.CommitContext
+{
+  @SuppressWarnings("unchecked")
+  public static final ProgressDistributable<InternalCommitContext>[] OPS = ProgressDistributor.array( //
+      new ProgressDistributable.Default<InternalCommitContext>()
+      {
+        public void runLoop(int index, InternalCommitContext commitContext, OMMonitor monitor) throws Exception
+        {
+          commitContext.write(monitor.fork());
+        }
+      }, //
+
+      new ProgressDistributable.Default<InternalCommitContext>()
+      {
+        public void runLoop(int index, InternalCommitContext commitContext, OMMonitor monitor) throws Exception
+        {
+          if (commitContext.getRollbackMessage() == null)
+          {
+            commitContext.commit(monitor.fork());
+          }
+          else
+          {
+            monitor.worked();
+          }
+        }
+      });
+
+  public InternalTransaction getTransaction();
+
+  public void preWrite();
+
+  public void write(OMMonitor monitor);
+
+  public void commit(OMMonitor monitor);
+
+  public void rollback(String message);
+
+  public void postCommit(boolean success);
+
+  /**
+   * @since 4.0
+   */
+  public InternalCDORevision[] getDetachedRevisions();
+
+  public void setNewPackageUnits(InternalCDOPackageUnit[] newPackageUnits);
+
+  public void setNewObjects(InternalCDORevision[] newObjects);
+
+  public void setDirtyObjectDeltas(InternalCDORevisionDelta[] dirtyObjectDeltas);
+
+  public void setDetachedObjects(CDOID[] detachedObjects);
+
+  /**
+   * @since 4.0
+   */
+  public void setDetachedObjectTypes(Map<CDOID, EClass> detachedObjectTypes);
+
+  public void setAutoReleaseLocksEnabled(boolean on);
+
+  public void setCommitComment(String comment);
+
+  /**
+   * @since 4.0
+   */
+  public void setLobs(ExtendedDataInputStream in);
+
+  public void addIDMapping(CDOID oldID, CDOID newID);
+
+  public void applyIDMappings(OMMonitor monitor);
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalCommitManager.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalCommitManager.java
new file mode 100644
index 0000000..6ebefcf
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalCommitManager.java
@@ -0,0 +1,47 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.spi.server;
+
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+
+import java.util.concurrent.ExecutionException;
+
+/**
+ * @author Eike Stepper
+ * @since 3.0
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface InternalCommitManager
+{
+  public InternalRepository getRepository();
+
+  public void setRepository(InternalRepository repository);
+
+  /**
+   * Create a future to execute commitContext in a different thread.
+   */
+  public void preCommit(InternalCommitContext commitContext, OMMonitor monitor);
+
+  /**
+   * Called after a commitContext is done successfully or not.
+   */
+  public void remove(InternalCommitContext commitContext);
+
+  public void rollback(InternalCommitContext commitContext);
+
+  /**
+   * Waiting for a commit to be done.
+   */
+  public void waitForTermination(InternalTransaction transaction) throws InterruptedException, ExecutionException;
+
+  public InternalCommitContext get(InternalTransaction transaction);
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalFailoverParticipant.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalFailoverParticipant.java
new file mode 100644
index 0000000..71a476b
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalFailoverParticipant.java
@@ -0,0 +1,24 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.spi.server;
+
+/**
+ * @author Eike Stepper
+ * @since 4.0
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface InternalFailoverParticipant extends InternalSynchronizableRepository
+{
+  public boolean isAllowBackupCommits();
+
+  public void setAllowBackupCommits(boolean allowBackupCommits);
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalLockManager.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalLockManager.java
new file mode 100644
index 0000000..ab8d9a2
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalLockManager.java
@@ -0,0 +1,139 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.spi.server;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.lock.IDurableLockingManager;
+import org.eclipse.emf.cdo.common.revision.CDOIDAndBranch;
+import org.eclipse.emf.cdo.server.ISession;
+import org.eclipse.emf.cdo.server.IView;
+
+import org.eclipse.net4j.util.concurrent.IRWOLockManager;
+import org.eclipse.net4j.util.concurrent.RWOLockManager.LockState;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * The type of the to-be-locked objects is either {@link CDOIDAndBranch} or {@link CDOID}, depending on whether
+ * branching is supported by the repository or not.
+ * 
+ * @author Eike Stepper
+ * @since 3.0
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface InternalLockManager extends IRWOLockManager<Object, IView>, IDurableLockingManager
+{
+  public InternalRepository getRepository();
+
+  public void setRepository(InternalRepository repository);
+
+  /**
+   * @since 4.0
+   */
+  public Object getLockEntryObject(Object key);
+
+  /**
+   * @since 4.0
+   */
+  public Object getLockKey(CDOID id, CDOBranch branch);
+
+  /**
+   * @since 4.0
+   */
+  public CDOID getLockKeyID(Object key);
+
+  /**
+   * @since 4.0
+   */
+  public Map<CDOID, LockGrade> getLocks(IView view);
+
+  /**
+   * @since 4.0
+   */
+  @Deprecated
+  public void lock(boolean explicit, LockType type, IView context, Collection<? extends Object> objectsToLock,
+      long timeout) throws InterruptedException;
+
+  /**
+   * @since 4.1
+   */
+  public List<LockState<Object, IView>> lock2(boolean explicit, LockType type, IView context,
+      Collection<? extends Object> objectsToLock, long timeout) throws InterruptedException;
+
+  /**
+   * Attempts to release for a given locktype, view and objects.
+   * 
+   * @throws IllegalMonitorStateException
+   *           Unlocking objects without lock.
+   * @since 4.0
+   */
+  @Deprecated
+  public void unlock(boolean explicit, LockType type, IView context, Collection<? extends Object> objectsToUnlock);
+
+  /**
+   * @since 4.1
+   */
+  public List<LockState<Object, IView>> unlock2(boolean explicit, LockType type, IView context,
+      Collection<? extends Object> objectsToUnlock);
+
+  /**
+   * Attempts to release all locks(read and write) for a given view.
+   * 
+   * @since 4.0
+   */
+  @Deprecated
+  public void unlock(boolean explicit, IView context);
+
+  /**
+   * @since 4.1
+   */
+  public List<LockState<Object, IView>> unlock2(boolean explicit, IView context);
+
+  /**
+   * @since 4.0
+   */
+  public LockArea createLockArea(InternalView view);
+
+  /**
+   * @since 4.1
+   */
+  public LockArea createLockArea(InternalView view, String lockAreaID);
+
+  /**
+   * @since 4.1
+   */
+  // TODO (CD) I've also added this to DurableLocking2 Refactoring opportunity?
+  public void updateLockArea(LockArea lockArea);
+
+  /**
+   * @since 4.0
+   */
+  public IView openView(ISession session, int viewID, boolean readOnly, String durableLockingID);
+
+  /**
+   * @since 4.1
+   */
+  public LockGrade getLockGrade(Object key);
+
+  /**
+   * @since 4.1
+   */
+  public LockState<Object, IView> getLockState(Object key);
+
+  /**
+   * @since 4.1
+   */
+  public void setLockState(Object key, LockState<Object, IView> lockState);
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalQueryManager.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalQueryManager.java
new file mode 100644
index 0000000..633026a
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalQueryManager.java
@@ -0,0 +1,32 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.spi.server;
+
+import org.eclipse.emf.cdo.common.util.CDOQueryInfo;
+
+/**
+ * @author Eike Stepper
+ * @since 3.0
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface InternalQueryManager
+{
+  public InternalRepository getRepository();
+
+  public void setRepository(InternalRepository repository);
+
+  public InternalQueryResult execute(InternalView view, CDOQueryInfo queryInfo);
+
+  public boolean isRunning(int queryID);
+
+  public void cancel(int queryID);
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalQueryResult.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalQueryResult.java
new file mode 100644
index 0000000..6c9479c
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalQueryResult.java
@@ -0,0 +1,32 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.spi.server;
+
+import org.eclipse.emf.cdo.common.util.BlockingCloseableIterator;
+import org.eclipse.emf.cdo.common.util.CDOQueryInfo;
+import org.eclipse.emf.cdo.common.util.CDOQueryQueue;
+
+/**
+ * @author Eike Stepper
+ * @since 3.0
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface InternalQueryResult extends BlockingCloseableIterator<Object>
+{
+  public int getQueryID();
+
+  public CDOQueryInfo getQueryInfo();
+
+  public InternalView getView();
+
+  public CDOQueryQueue<Object> getQueue();
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalRepository.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalRepository.java
new file mode 100644
index 0000000..eb8c0b5
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalRepository.java
@@ -0,0 +1,230 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.spi.server;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.commit.CDOChangeSetData;
+import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.lob.CDOLobHandler;
+import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionHandler;
+import org.eclipse.emf.cdo.common.revision.CDORevisionKey;
+import org.eclipse.emf.cdo.server.IQueryHandlerProvider;
+import org.eclipse.emf.cdo.server.IRepository;
+import org.eclipse.emf.cdo.server.IStoreAccessor;
+import org.eclipse.emf.cdo.server.ITransaction;
+import org.eclipse.emf.cdo.spi.common.CDOReplicationContext;
+import org.eclipse.emf.cdo.spi.common.CDOReplicationInfo;
+import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranchManager;
+import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranchManager.BranchLoader;
+import org.eclipse.emf.cdo.spi.common.commit.CDORevisionAvailabilityInfo;
+import org.eclipse.emf.cdo.spi.common.commit.InternalCDOCommitInfoManager;
+import org.eclipse.emf.cdo.spi.common.commit.InternalCDOCommitInfoManager.CommitInfoLoader;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry.PackageLoader;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry.PackageProcessor;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager.RevisionLoader;
+
+import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.spi.cdo.CDOSessionProtocol.LockObjectsResult;
+import org.eclipse.emf.spi.cdo.CDOSessionProtocol.UnlockObjectsResult;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Semaphore;
+
+/**
+ * @author Eike Stepper
+ * @since 3.0
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface InternalRepository extends IRepository, PackageProcessor, PackageLoader, BranchLoader, RevisionLoader,
+    CommitInfoLoader
+{
+  public void setName(String name);
+
+  public void setType(Type type);
+
+  public void setState(State state);
+
+  public InternalStore getStore();
+
+  public void setStore(InternalStore store);
+
+  public void setProperties(Map<String, String> properties);
+
+  public InternalCDOBranchManager getBranchManager();
+
+  public void setBranchManager(InternalCDOBranchManager branchManager);
+
+  /**
+   * @since 4.1
+   */
+  public Semaphore getPackageRegistryCommitLock();
+
+  /**
+   * Same as calling {@link #getPackageRegistry(boolean) getPackageRegistry(true)}.
+   */
+  public InternalCDOPackageRegistry getPackageRegistry();
+
+  public InternalCDOPackageRegistry getPackageRegistry(boolean considerCommitContext);
+
+  public InternalCDORevisionManager getRevisionManager();
+
+  public void setRevisionManager(InternalCDORevisionManager revisionManager);
+
+  public InternalCDOCommitInfoManager getCommitInfoManager();
+
+  public InternalSessionManager getSessionManager();
+
+  public void setSessionManager(InternalSessionManager sessionManager);
+
+  public InternalLockManager getLockManager();
+
+  public InternalQueryManager getQueryManager();
+
+  public void setQueryHandlerProvider(IQueryHandlerProvider queryHandlerProvider);
+
+  public InternalCommitManager getCommitManager();
+
+  public InternalCommitContext createCommitContext(InternalTransaction transaction);
+
+  /**
+   * Returns a commit time stamp that is guaranteed to be unique in this repository. At index 1 of the returned
+   * <code>long</code> array is the previous commit time.
+   * 
+   * @since 4.0
+   */
+  public long[] createCommitTimeStamp(OMMonitor monitor);
+
+  /**
+   * Like {@link #createCommitTimeStamp(OMMonitor)}, but forces the repository to use the timestamp value passed in as
+   * the argument. This should be called only to force the timestamp of the first commit of a new repository to be equal
+   * to its creation time.
+   * 
+   * @since 4.0
+   */
+  public long[] forceCommitTimeStamp(long timestamp, OMMonitor monitor);
+
+  /**
+   * Notifies the repository of the completion of a commit. The value passed in must be a value obtained earlier through
+   * {@link #createCommitTimeStamp(OMMonitor)}
+   * 
+   * @since 4.0
+   */
+  public void endCommit(long timeStamp);
+
+  /**
+   * Notifies the repository of the failure of a commit. The value passed in must be a value obtained earlier through
+   * {@link #createCommitTimeStamp(OMMonitor)}
+   * 
+   * @since 4.0
+   */
+  public void failCommit(long timeStamp);
+
+  /**
+   * @since 4.0
+   */
+  public void sendCommitNotification(InternalSession sender, CDOCommitInfo commitInfo);
+
+  public void setRootResourceID(CDOID rootResourceID);
+
+  /**
+   * @since 4.0
+   */
+  public void setLastCommitTimeStamp(long commitTimeStamp);
+
+  public IStoreAccessor ensureChunk(InternalCDORevision revision, EStructuralFeature feature, int chunkStart,
+      int chunkEnd);
+
+  public void notifyReadAccessHandlers(InternalSession session, CDORevision[] revisions,
+      List<CDORevision> additionalRevisions);
+
+  public void notifyWriteAccessHandlers(ITransaction transaction, IStoreAccessor.CommitContext commitContext,
+      boolean beforeCommit, OMMonitor monitor);
+
+  public void replicate(CDOReplicationContext context);
+
+  public CDOReplicationInfo replicateRaw(CDODataOutput out, int lastReplicatedBranchID, long lastReplicatedCommitTime)
+      throws IOException;
+
+  public CDOChangeSetData getChangeSet(CDOBranchPoint startPoint, CDOBranchPoint endPoint);
+
+  /**
+   * @since 4.0
+   */
+  public Set<CDOID> getMergeData(CDORevisionAvailabilityInfo targetInfo, CDORevisionAvailabilityInfo sourceInfo,
+      CDORevisionAvailabilityInfo targetBaseInfo, CDORevisionAvailabilityInfo sourceBaseInfo, OMMonitor monitor);
+
+  /**
+   * @since 4.0
+   */
+  public void queryLobs(List<byte[]> ids);
+
+  /**
+   * @since 4.0
+   */
+  public void handleLobs(long fromTime, long toTime, CDOLobHandler handler) throws IOException;
+
+  /**
+   * @since 4.0
+   */
+  public void loadLob(byte[] id, OutputStream out) throws IOException;
+
+  /**
+   * @since 4.0
+   */
+  public void handleRevisions(EClass eClass, CDOBranch branch, boolean exactBranch, long timeStamp, boolean exactTime,
+      CDORevisionHandler handler);
+
+  /**
+   * @since 4.0
+   */
+  public boolean isSkipInitialization();
+
+  /**
+   * @since 4.0
+   */
+  public void setSkipInitialization(boolean skipInitialization);
+
+  /**
+   * @since 4.0
+   */
+  public void initSystemPackages();
+
+  /**
+   * @since 4.0
+   */
+  public void initMainBranch(InternalCDOBranchManager branchManager, long timeStamp);
+
+  /**
+   * @since 4.1
+   */
+  public LockObjectsResult lock(InternalView view, LockType lockType, List<CDORevisionKey> revisionKeys, long timeout);
+
+  /**
+   * @since 4.1
+   */
+  public UnlockObjectsResult unlock(InternalView view, LockType lockType, List<CDOID> objectIDs);
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalRepositorySynchronizer.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalRepositorySynchronizer.java
new file mode 100644
index 0000000..20151f3
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalRepositorySynchronizer.java
@@ -0,0 +1,35 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.spi.server;
+
+import org.eclipse.emf.cdo.server.IRepositorySynchronizer;
+import org.eclipse.emf.cdo.session.CDOSessionConfigurationFactory;
+
+import org.eclipse.net4j.util.lifecycle.ILifecycle;
+
+import org.eclipse.emf.spi.cdo.InternalCDOSession;
+
+/**
+ * @author Eike Stepper
+ * @since 3.0
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface InternalRepositorySynchronizer extends IRepositorySynchronizer, ILifecycle
+{
+  public InternalSynchronizableRepository getLocalRepository();
+
+  public void setLocalRepository(InternalSynchronizableRepository localRepository);
+
+  public void setRemoteSessionConfigurationFactory(CDOSessionConfigurationFactory remoteSessionConfigurationFactory);
+
+  public InternalCDOSession getRemoteSession();
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalSession.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalSession.java
new file mode 100644
index 0000000..9195c68
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalSession.java
@@ -0,0 +1,86 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.spi.server;
+
+import org.eclipse.emf.cdo.common.CDOCommonRepository;
+import org.eclipse.emf.cdo.common.CDOCommonSession;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.id.CDOIDProvider;
+import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.server.ISession;
+import org.eclipse.emf.cdo.session.remote.CDORemoteSessionMessage;
+import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranch;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Eike Stepper
+ * @since 3.0
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface InternalSession extends ISession, CDOIDProvider, CDOCommonSession.Options
+{
+  public static final int TEMP_VIEW_ID = 0;
+
+  public InternalSessionManager getManager();
+
+  public InternalView[] getViews();
+
+  public InternalView getView(int viewID);
+
+  public InternalView openView(int viewID, CDOBranchPoint branchPoint);
+
+  public InternalTransaction openTransaction(int viewID, CDOBranchPoint branchPoint);
+
+  public void viewClosed(InternalView view);
+
+  public void setSubscribed(boolean subscribed);
+
+  public void collectContainedRevisions(InternalCDORevision revision, CDOBranchPoint branchPoint, int referenceChunk,
+      Set<CDOID> revisions, List<CDORevision> additionalRevisions);
+
+  public void sendRepositoryTypeNotification(CDOCommonRepository.Type oldType, CDOCommonRepository.Type newType)
+      throws Exception;
+
+  /**
+   * @deprecated use
+   *             {@link #sendRepositoryStateNotification(org.eclipse.emf.cdo.common.CDOCommonRepository.State, org.eclipse.emf.cdo.common.CDOCommonRepository.State, CDOID)}
+   *             instead
+   */
+  @Deprecated
+  public void sendRepositoryStateNotification(CDOCommonRepository.State oldState, CDOCommonRepository.State newState)
+      throws Exception;
+
+  /**
+   * @since 4.1
+   */
+  public void sendRepositoryStateNotification(CDOCommonRepository.State oldState, CDOCommonRepository.State newState,
+      CDOID rootResourceID) throws Exception;
+
+  public void sendBranchNotification(InternalCDOBranch branch) throws Exception;
+
+  public void sendCommitNotification(CDOCommitInfo commitInfo) throws Exception;
+
+  public void sendRemoteSessionNotification(InternalSession sender, byte opcode) throws Exception;
+
+  public void sendRemoteMessageNotification(InternalSession sender, CDORemoteSessionMessage message) throws Exception;
+
+  /**
+   * @since 4.1
+   */
+  public void sendLockNotification(CDOLockChangeInfo lockChangeInfo) throws Exception;
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalSessionManager.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalSessionManager.java
new file mode 100644
index 0000000..435b78e
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalSessionManager.java
@@ -0,0 +1,79 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.spi.server;
+
+import org.eclipse.emf.cdo.common.CDOCommonRepository;
+import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
+import org.eclipse.emf.cdo.server.ISessionManager;
+import org.eclipse.emf.cdo.session.remote.CDORemoteSessionMessage;
+import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranch;
+
+import org.eclipse.net4j.util.security.IUserManager;
+
+import java.util.List;
+
+/**
+ * @author Eike Stepper
+ * @since 3.0
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface InternalSessionManager extends ISessionManager
+{
+  public InternalRepository getRepository();
+
+  public void setRepository(InternalRepository repository);
+
+  public void setUserManager(IUserManager userManager);
+
+  public InternalSession[] getSessions();
+
+  public InternalSession getSession(int sessionID);
+
+  /**
+   * @return Never <code>null</code>
+   */
+  public InternalSession openSession(ISessionProtocol sessionProtocol);
+
+  public void sessionClosed(InternalSession session);
+
+  public void sendRepositoryTypeNotification(CDOCommonRepository.Type oldType, CDOCommonRepository.Type newType);
+
+  /**
+   * @deprecated use
+   *             {@link #sendRepositoryStateNotification(org.eclipse.emf.cdo.common.CDOCommonRepository.State, org.eclipse.emf.cdo.common.CDOCommonRepository.State, CDOID)}
+   *             instead
+   */
+  @Deprecated
+  public void sendRepositoryStateNotification(CDOCommonRepository.State oldState, CDOCommonRepository.State newState);
+
+  /**
+   * @since 4.1
+   */
+  public void sendRepositoryStateNotification(CDOCommonRepository.State oldState, CDOCommonRepository.State newState,
+      CDOID rootResourceID);
+
+  public void sendBranchNotification(InternalSession sender, InternalCDOBranch branch);
+
+  public void sendCommitNotification(InternalSession sender, CDOCommitInfo commitInfo);
+
+  /**
+   * @since 4.1
+   */
+  public void sendLockNotification(InternalSession sender, CDOLockChangeInfo lockChangeInfo);
+
+  public void sendRemoteSessionNotification(InternalSession sender, byte opcode);
+
+  public List<Integer> sendRemoteMessageNotification(InternalSession sender, CDORemoteSessionMessage message,
+      int[] recipients);
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalStore.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalStore.java
new file mode 100644
index 0000000..af99668
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalStore.java
@@ -0,0 +1,112 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.spi.server;
+
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.server.IRepository;
+import org.eclipse.emf.cdo.server.IStore;
+
+import org.eclipse.net4j.util.lifecycle.ILifecycle;
+
+/**
+ * @author Eike Stepper
+ * @since 3.0
+ */
+public interface InternalStore extends IStore, ILifecycle
+{
+  public InternalRepository getRepository();
+
+  public void setRepository(IRepository repository);
+
+  public void setRevisionTemporality(RevisionTemporality revisionTemporality);
+
+  public void setRevisionParallelism(RevisionParallelism revisionParallelism);
+
+  public int getNextBranchID();
+
+  public int getNextLocalBranchID();
+
+  public void setLastBranchID(int lastBranchID);
+
+  public void setLastLocalBranchID(int lastLocalBranchID);
+
+  public void setLastCommitTime(long lastCommitTime);
+
+  public void setLastNonLocalCommitTime(long lastNonLocalCommitTime);
+
+  /**
+   * @since 4.0
+   */
+  public boolean isLocal(CDOID id);
+
+  /**
+   * @since 4.0
+   */
+  public boolean isDropAllDataOnActivate();
+
+  /**
+   * @since 4.0
+   */
+  public void setDropAllDataOnActivate(boolean dropAllDataOnActivate);
+
+  /**
+   * @since 4.0
+   */
+  public void setCreationTime(long creationTime);
+
+  /**
+   * @author Eike Stepper
+   * @since 4.0
+   */
+  public interface NoExternalReferences
+  {
+  }
+
+  /**
+   * @author Eike Stepper
+   * @since 4.0
+   */
+  public interface NoQueryXRefs
+  {
+  }
+
+  /**
+   * @author Eike Stepper
+   * @since 4.0
+   */
+  public interface NoLargeObjects
+  {
+  }
+
+  /**
+   * @author Eike Stepper
+   * @since 4.0
+   */
+  public interface NoFeatureMaps
+  {
+  }
+
+  /**
+   * @author Eike Stepper
+   * @since 4.0
+   */
+  public interface NoHandleRevisions
+  {
+  }
+
+  /**
+   * @author Eike Stepper
+   * @since 4.0
+   */
+  public interface NoRawAccess
+  {
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalSynchronizableRepository.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalSynchronizableRepository.java
new file mode 100644
index 0000000..f4c3298
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalSynchronizableRepository.java
@@ -0,0 +1,36 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.spi.server;
+
+import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfoHandler;
+import org.eclipse.emf.cdo.server.ISynchronizableRepository;
+import org.eclipse.emf.cdo.spi.common.CDORawReplicationContext;
+import org.eclipse.emf.cdo.spi.common.CDOReplicationContext;
+
+/**
+ * @author Eike Stepper
+ * @since 3.0
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface InternalSynchronizableRepository extends ISynchronizableRepository, InternalRepository,
+    CDOReplicationContext, CDORawReplicationContext, CDOLockChangeInfoHandler
+{
+  public InternalRepositorySynchronizer getSynchronizer();
+
+  public void setSynchronizer(InternalRepositorySynchronizer synchronizer);
+
+  public InternalSession getReplicatorSession();
+
+  public void setLastReplicatedBranchID(int lastReplicatedBranchID);
+
+  public void setLastReplicatedCommitTime(long lastReplicatedCommitTime);
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalTransaction.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalTransaction.java
new file mode 100644
index 0000000..2f51ae2
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalTransaction.java
@@ -0,0 +1,24 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.spi.server;
+
+import org.eclipse.emf.cdo.server.ITransaction;
+
+/**
+ * @author Eike Stepper
+ * @since 3.0
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface InternalTransaction extends ITransaction, InternalView
+{
+  public InternalCommitContext createCommitContext();
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalView.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalView.java
new file mode 100644
index 0000000..8adca8f
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalView.java
@@ -0,0 +1,56 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.spi.server;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
+import org.eclipse.emf.cdo.server.IView;
+
+import org.eclipse.net4j.util.lifecycle.ILifecycle;
+
+import java.util.List;
+
+/**
+ * @author Eike Stepper
+ * @since 3.0
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface InternalView extends IView, ILifecycle
+{
+  public InternalSession getSession();
+
+  public InternalRepository getRepository();
+
+  public void setBranchPoint(CDOBranchPoint branchPoint);
+
+  /**
+   * @since 4.0
+   */
+  public void setDurableLockingID(String durableLockingID);
+
+  /**
+   * @since 4.0
+   */
+  public void changeTarget(CDOBranchPoint branchPoint, List<CDOID> invalidObjects,
+      List<CDORevisionDelta> allChangedObjects, List<CDOID> allDetachedObjects);
+
+  public void subscribe(CDOID id);
+
+  public void unsubscribe(CDOID id);
+
+  public boolean hasSubscription(CDOID id);
+
+  public void clearChangeSubscription();
+
+  public void doClose();
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/LongIDStore.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/LongIDStore.java
new file mode 100644
index 0000000..908e5ba
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/LongIDStore.java
@@ -0,0 +1,120 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.spi.server;
+
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.id.CDOID.ObjectType;
+import org.eclipse.emf.cdo.common.id.CDOIDUtil;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+
+import org.eclipse.net4j.util.ReflectUtil.ExcludeFromDump;
+
+import java.util.Collections;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * @author Eike Stepper
+ * @since 2.0
+ */
+public abstract class LongIDStore extends Store
+{
+  /**
+   * @since 3.0
+   */
+  public static final Set<ObjectType> OBJECT_ID_TYPES = Collections.singleton(CDOID.ObjectType.LONG);
+
+  /**
+   * @since 3.0
+   */
+  public static final long NULL = CDOIDUtil.getLong(CDOID.NULL);
+
+  @ExcludeFromDump
+  private transient AtomicLong lastObjectID = new AtomicLong();
+
+  @ExcludeFromDump
+  private transient AtomicLong nextLocalObjectID = new AtomicLong(Long.MAX_VALUE);
+
+  public LongIDStore(String type, Set<ChangeFormat> supportedChangeFormats,
+      Set<RevisionTemporality> supportedRevisionTemporalities, Set<RevisionParallelism> supportedRevisionParallelisms)
+  {
+    super(type, OBJECT_ID_TYPES, supportedChangeFormats, supportedRevisionTemporalities, supportedRevisionParallelisms);
+  }
+
+  /**
+   * @since 4.0
+   */
+  public CDOID createObjectID(String val)
+  {
+    Long id = Long.valueOf(val);
+    return CDOIDUtil.createLong(id);
+  }
+
+  public long getLastObjectID()
+  {
+    return lastObjectID.get();
+  }
+
+  public void setLastObjectID(long lastObjectID)
+  {
+    this.lastObjectID.set(lastObjectID);
+  }
+
+  /**
+   * @since 3.0
+   */
+  public long getNextLocalObjectID()
+  {
+    return nextLocalObjectID.get();
+  }
+
+  /**
+   * @since 3.0
+   */
+  public void setNextLocalObjectID(long nextLocalObjectID)
+  {
+    this.nextLocalObjectID.set(nextLocalObjectID);
+  }
+
+  /**
+   * @since 4.0
+   */
+  public CDOID getNextCDOID(LongIDStoreAccessor accessor, CDORevision revision)
+  {
+    if (revision.getBranch().isLocal())
+    {
+      return CDOIDUtil.createLong(nextLocalObjectID.getAndDecrement());
+    }
+
+    return CDOIDUtil.createLong(lastObjectID.incrementAndGet());
+  }
+
+  /**
+   * @since 4.0
+   */
+  public boolean isLocal(CDOID id)
+  {
+    long value = CDOIDUtil.getLong(id);
+    return value > nextLocalObjectID.get();
+  }
+
+  /**
+   * @since 4.0
+   */
+  public void ensureLastObjectID(CDOID id)
+  {
+    long addedID = CDOIDUtil.getLong(id);
+    if (addedID > getLastObjectID())
+    {
+      setLastObjectID(addedID);
+    }
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/LongIDStoreAccessor.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/LongIDStoreAccessor.java
new file mode 100644
index 0000000..803368e
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/LongIDStoreAccessor.java
@@ -0,0 +1,50 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Simon McDuff - bug 201266
+ *    Simon McDuff - bug 213402
+ */
+package org.eclipse.emf.cdo.spi.server;
+
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.server.ISession;
+import org.eclipse.emf.cdo.server.ITransaction;
+
+/**
+ * @since 2.0
+ * @author Eike Stepper
+ */
+public abstract class LongIDStoreAccessor extends StoreAccessor
+{
+  protected LongIDStoreAccessor(Store store, ISession session)
+  {
+    super(store, session);
+  }
+
+  protected LongIDStoreAccessor(Store store, ITransaction transaction)
+  {
+    super(store, transaction);
+  }
+
+  /**
+   * @since 4.0
+   */
+  @Override
+  public LongIDStore getStore()
+  {
+    return (LongIDStore)super.getStore();
+  }
+
+  @Override
+  protected CDOID getNextCDOID(CDORevision revision)
+  {
+    return getStore().getNextCDOID(this, revision);
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/ObjectWriteAccessHandler.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/ObjectWriteAccessHandler.java
new file mode 100644
index 0000000..8db6cb5
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/ObjectWriteAccessHandler.java
@@ -0,0 +1,159 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.spi.server;
+
+import org.eclipse.emf.cdo.CDOObject;
+import org.eclipse.emf.cdo.server.CDOServerUtil;
+import org.eclipse.emf.cdo.server.IRepository.WriteAccessHandler;
+import org.eclipse.emf.cdo.server.IStoreAccessor;
+import org.eclipse.emf.cdo.server.IStoreAccessor.CommitContext;
+import org.eclipse.emf.cdo.server.ITransaction;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+import org.eclipse.emf.cdo.util.CDOUtil;
+import org.eclipse.emf.cdo.view.CDOView;
+
+import org.eclipse.net4j.util.lifecycle.LifecycleUtil;
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+
+import org.eclipse.emf.ecore.EObject;
+
+/**
+ * @author Eike Stepper
+ * @since 4.0
+ */
+public class ObjectWriteAccessHandler implements WriteAccessHandler
+{
+  private boolean legacyModeEnabled;
+
+  private IStoreAccessor.CommitContext commitContext;
+
+  private CDOView view;
+
+  private EObject[] newObjects;
+
+  private EObject[] dirtyObjects;
+
+  public ObjectWriteAccessHandler()
+  {
+  }
+
+  public ObjectWriteAccessHandler(boolean legacyModeEnabled)
+  {
+    this.legacyModeEnabled = legacyModeEnabled;
+  }
+
+  public final boolean isLegacyModeEnabled()
+  {
+    return legacyModeEnabled;
+  }
+
+  protected final IStoreAccessor.CommitContext getCommitContext()
+  {
+    return commitContext;
+  }
+
+  protected final ITransaction getTransaction()
+  {
+    return commitContext.getTransaction();
+  }
+
+  protected final CDOView getView()
+  {
+    if (view == null)
+    {
+      view = CDOServerUtil.openView(commitContext, legacyModeEnabled);
+    }
+
+    return view;
+  }
+
+  protected final EObject[] getNewObjects()
+  {
+    if (newObjects == null)
+    {
+      InternalCDORevision[] newRevisions = commitContext.getNewObjects();
+      newObjects = new EObject[newRevisions.length];
+      CDOView view = getView();
+
+      for (int i = 0; i < newRevisions.length; i++)
+      {
+        InternalCDORevision newRevision = newRevisions[i];
+        CDOObject newObject = view.getObject(newRevision.getID());
+        newObjects[i] = CDOUtil.getEObject(newObject);
+      }
+    }
+
+    return newObjects;
+  }
+
+  protected final EObject[] getDirtyObjects()
+  {
+    if (dirtyObjects == null)
+    {
+      InternalCDORevision[] dirtyRevisions = commitContext.getDirtyObjects();
+      dirtyObjects = new EObject[dirtyRevisions.length];
+      CDOView view = getView();
+
+      for (int i = 0; i < dirtyRevisions.length; i++)
+      {
+        InternalCDORevision dirtyRevision = dirtyRevisions[i];
+        CDOObject dirtyObject = view.getObject(dirtyRevision.getID());
+        dirtyObjects[i] = CDOUtil.getEObject(dirtyObject);
+      }
+    }
+
+    return dirtyObjects;
+  }
+
+  public final void handleTransactionBeforeCommitting(ITransaction transaction,
+      IStoreAccessor.CommitContext commitContext, OMMonitor monitor) throws RuntimeException
+  {
+    try
+    {
+      this.commitContext = commitContext;
+      handleTransactionBeforeCommitting(monitor);
+    }
+    finally
+    {
+      LifecycleUtil.deactivate(view);
+      view = null;
+      dirtyObjects = null;
+      newObjects = null;
+      this.commitContext = null;
+    }
+  }
+
+  public final void handleTransactionAfterCommitted(ITransaction transaction, CommitContext commitContext,
+      OMMonitor monitor)
+  {
+    try
+    {
+      this.commitContext = commitContext;
+      handleTransactionAfterCommitted(monitor);
+    }
+    finally
+    {
+      LifecycleUtil.deactivate(view);
+      view = null;
+      dirtyObjects = null;
+      newObjects = null;
+      this.commitContext = null;
+    }
+  }
+
+  protected void handleTransactionBeforeCommitting(OMMonitor monitor) throws RuntimeException
+  {
+  }
+
+  protected void handleTransactionAfterCommitted(OMMonitor monitor)
+  {
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/PluginRepositoryProvider.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/PluginRepositoryProvider.java
new file mode 100644
index 0000000..c084dce
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/PluginRepositoryProvider.java
@@ -0,0 +1,27 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.spi.server;
+
+import org.eclipse.net4j.util.container.IPluginContainer;
+
+/**
+ * @author Eike Stepper
+ * @since 2.0
+ */
+public final class PluginRepositoryProvider extends ContainerRepositoryProvider
+{
+  public static final PluginRepositoryProvider INSTANCE = new PluginRepositoryProvider();
+
+  private PluginRepositoryProvider()
+  {
+    super(IPluginContainer.INSTANCE);
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/QueryHandlerFactory.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/QueryHandlerFactory.java
new file mode 100644
index 0000000..10aa1d8
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/QueryHandlerFactory.java
@@ -0,0 +1,35 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.spi.server;
+
+import org.eclipse.emf.cdo.server.IQueryHandler;
+
+import org.eclipse.net4j.util.factory.Factory;
+import org.eclipse.net4j.util.factory.ProductCreationException;
+
+/**
+ * @author Eike Stepper
+ * @since 2.0
+ */
+public abstract class QueryHandlerFactory extends Factory
+{
+  public static final String PRODUCT_GROUP = "org.eclipse.emf.cdo.server.queryHandlerFactories"; //$NON-NLS-1$
+
+  public QueryHandlerFactory(String language)
+  {
+    super(PRODUCT_GROUP, language);
+  }
+
+  /**
+   * @since 3.0
+   */
+  public abstract IQueryHandler create(String description) throws ProductCreationException;
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/RepositoryConfigurator.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/RepositoryConfigurator.java
new file mode 100644
index 0000000..e58dc79
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/RepositoryConfigurator.java
@@ -0,0 +1,346 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Lothar Werzinger - support for configuring user managers
+ */
+package org.eclipse.emf.cdo.spi.server;
+
+import org.eclipse.emf.cdo.internal.server.SessionManager;
+import org.eclipse.emf.cdo.internal.server.bundle.OM;
+import org.eclipse.emf.cdo.server.CDOServerUtil;
+import org.eclipse.emf.cdo.server.IRepository;
+import org.eclipse.emf.cdo.server.IRepositoryFactory;
+import org.eclipse.emf.cdo.server.IStore;
+import org.eclipse.emf.cdo.server.IStoreFactory;
+
+import org.eclipse.net4j.util.ObjectUtil;
+import org.eclipse.net4j.util.StringUtil;
+import org.eclipse.net4j.util.container.IManagedContainer;
+import org.eclipse.net4j.util.om.trace.ContextTracer;
+import org.eclipse.net4j.util.security.IUserManager;
+
+import org.eclipse.emf.ecore.EPackage;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.Platform;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Eike Stepper
+ * @since 4.0
+ */
+public class RepositoryConfigurator
+{
+  private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_REPOSITORY, RepositoryConfigurator.class);
+
+  private IManagedContainer container;
+
+  private Map<String, IRepositoryFactory> repositoryFactories = new HashMap<String, IRepositoryFactory>();
+
+  private Map<String, IStoreFactory> storeFactories = new HashMap<String, IStoreFactory>();
+
+  public RepositoryConfigurator()
+  {
+    this(null);
+  }
+
+  public RepositoryConfigurator(IManagedContainer container)
+  {
+    this.container = container;
+  }
+
+  public IManagedContainer getContainer()
+  {
+    return container;
+  }
+
+  public Map<String, IRepositoryFactory> getRepositoryFactories()
+  {
+    return repositoryFactories;
+  }
+
+  public Map<String, IStoreFactory> getStoreFactories()
+  {
+    return storeFactories;
+  }
+
+  public IRepository[] configure(File configFile) throws ParserConfigurationException, SAXException, IOException,
+      CoreException
+  {
+    if (TRACER.isEnabled())
+    {
+      TRACER.trace("Configuring CDO server from " + configFile.getAbsolutePath()); //$NON-NLS-1$
+    }
+
+    List<IRepository> repositories = new ArrayList<IRepository>();
+    Document document = getDocument(configFile);
+    NodeList elements = document.getElementsByTagName("repository"); //$NON-NLS-1$
+    for (int i = 0; i < elements.getLength(); i++)
+    {
+      Element repositoryConfig = (Element)elements.item(i);
+      IRepository repository = getRepository(repositoryConfig);
+      repositories.add(repository);
+
+      if (container != null)
+      {
+        CDOServerUtil.addRepository(container, repository);
+      }
+    }
+
+    return repositories.toArray(new IRepository[repositories.size()]);
+  }
+
+  protected Document getDocument(File configFile) throws ParserConfigurationException, SAXException, IOException
+  {
+    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+    DocumentBuilder builder = factory.newDocumentBuilder();
+    return builder.parse(configFile);
+  }
+
+  protected IRepositoryFactory getRepositoryFactory(String type) throws CoreException
+  {
+    IRepositoryFactory factory = repositoryFactories.get(type);
+    if (factory == null)
+    {
+      factory = createExecutableExtension("repositoryFactories", "repositoryFactory", //$NON-NLS-1$ //$NON-NLS-2$ 
+          "repositoryType", type); //$NON-NLS-1$
+    }
+
+    if (factory == null)
+    {
+      throw new IllegalStateException("CDORepositoryInfo factory not found: " + type); //$NON-NLS-1$
+    }
+
+    return factory;
+  }
+
+  protected IRepository getRepository(Element repositoryConfig) throws CoreException
+  {
+    String repositoryName = repositoryConfig.getAttribute("name"); //$NON-NLS-1$
+    if (StringUtil.isEmpty(repositoryName))
+    {
+      throw new IllegalArgumentException("CDORepositoryInfo name is missing or empty"); //$NON-NLS-1$
+    }
+
+    String repositoryType = repositoryConfig.getAttribute("type"); //$NON-NLS-1$
+    if (StringUtil.isEmpty(repositoryType))
+    {
+      repositoryType = RepositoryFactory.TYPE;
+    }
+
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Configuring repository {0} (type={1})", repositoryName, repositoryType); //$NON-NLS-1$
+    }
+
+    Map<String, String> properties = getProperties(repositoryConfig, 1);
+
+    Element storeConfig = getStoreConfig(repositoryConfig);
+    IStore store = createStore(repositoryName, properties, storeConfig);
+
+    InternalRepository repository = (InternalRepository)getRepository(repositoryType);
+    repository.setName(repositoryName);
+    repository.setStore((InternalStore)store);
+    repository.setProperties(properties);
+
+    Element userManagerConfig = getUserManagerConfig(repositoryConfig);
+    if (userManagerConfig != null)
+    {
+      IUserManager userManager = getUserManager(userManagerConfig);
+      if (userManager != null)
+      {
+        InternalSessionManager sessionManager = repository.getSessionManager();
+        if (sessionManager == null)
+        {
+          sessionManager = new SessionManager();
+          repository.setSessionManager(sessionManager);
+        }
+
+        sessionManager.setUserManager(userManager);
+      }
+    }
+
+    EPackage[] initialPackages = getInitialPackages(repositoryConfig);
+    if (initialPackages.length != 0)
+    {
+      repository.setInitialPackages(initialPackages);
+    }
+
+    return repository;
+  }
+
+  protected IRepository getRepository(String repositoryType) throws CoreException
+  {
+    IRepositoryFactory factory = getRepositoryFactory(repositoryType);
+    return factory.createRepository();
+  }
+
+  protected Element getUserManagerConfig(Element repositoryConfig)
+  {
+    NodeList userManagerConfig = repositoryConfig.getElementsByTagName("userManager"); //$NON-NLS-1$
+    if (userManagerConfig.getLength() > 1)
+    {
+      String repositoryName = repositoryConfig.getAttribute("name"); //$NON-NLS-1$
+      throw new IllegalStateException("At most one user manager must be configured for repository " + repositoryName); //$NON-NLS-1$
+    }
+
+    return (Element)(userManagerConfig.getLength() > 0 ? userManagerConfig.item(0) : null);
+  }
+
+  protected IUserManager getUserManager(Element userManagerConfig) throws CoreException
+  {
+    String type = userManagerConfig.getAttribute("type"); //$NON-NLS-1$
+    String description = userManagerConfig.getAttribute("description"); //$NON-NLS-1$
+    return getUserManager(type, description);
+  }
+
+  protected IUserManager getUserManager(String type, String description) throws CoreException
+  {
+    IUserManager userManager = (IUserManager)container.getElement("org.eclipse.net4j.userManagers", type, description); //$NON-NLS-1$
+    if (userManager == null)
+    {
+      throw new IllegalStateException("UserManager factory not found: " + type); //$NON-NLS-1$
+    }
+
+    return userManager;
+  }
+
+  protected EPackage[] getInitialPackages(Element repositoryConfig)
+  {
+    List<EPackage> result = new ArrayList<EPackage>();
+
+    NodeList initialPackagesConfig = repositoryConfig.getElementsByTagName("initialPackage"); //$NON-NLS-1$
+    for (int i = 0; i < initialPackagesConfig.getLength(); i++)
+    {
+      Element initialPackageConfig = (Element)initialPackagesConfig.item(i);
+      String nsURI = initialPackageConfig.getAttribute("nsURI"); //$NON-NLS-1$
+      if (nsURI == null)
+      {
+        throw new IllegalStateException("nsURI missing for initialPackage element"); //$NON-NLS-1$
+      }
+
+      EPackage initialPackage = EPackage.Registry.INSTANCE.getEPackage(nsURI);
+      if (initialPackage == null)
+      {
+        throw new IllegalStateException("Initial package not found in global package registry: " + nsURI); //$NON-NLS-1$
+      }
+
+      result.add(initialPackage);
+    }
+
+    return result.toArray(new EPackage[result.size()]);
+  }
+
+  protected Element getStoreConfig(Element repositoryConfig)
+  {
+    NodeList storeConfigs = repositoryConfig.getElementsByTagName("store"); //$NON-NLS-1$
+    if (storeConfigs.getLength() == 0)
+    {
+      String repositoryName = repositoryConfig.getAttribute("name"); //$NON-NLS-1$
+      throw new IllegalStateException("A store must be configured for repository " + repositoryName); //$NON-NLS-1$
+    }
+
+    return (Element)storeConfigs.item(0);
+  }
+
+  protected IStoreFactory getStoreFactory(String type) throws CoreException
+  {
+    IStoreFactory factory = storeFactories.get(type);
+    if (factory == null)
+    {
+      factory = createExecutableExtension("storeFactories", "storeFactory", "storeType", type); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+    }
+
+    if (factory == null)
+    {
+      throw new IllegalStateException("Store factory not found: " + type); //$NON-NLS-1$
+    }
+
+    return factory;
+  }
+
+  protected IStore createStore(String repositoryName, Map<String, String> repositoryProperties, Element storeConfig)
+      throws CoreException
+  {
+    String type = storeConfig.getAttribute("type"); //$NON-NLS-1$
+    IStoreFactory storeFactory = getStoreFactory(type);
+    return storeFactory.createStore(repositoryName, repositoryProperties, storeConfig);
+  }
+
+  public static Map<String, String> getProperties(Element element, int levels)
+  {
+    Map<String, String> properties = new HashMap<String, String>();
+    collectProperties(element, "", properties, levels); //$NON-NLS-1$
+    return properties;
+  }
+
+  private static void collectProperties(Element element, String prefix, Map<String, String> properties, int levels)
+  {
+    if ("property".equals(element.getNodeName())) //$NON-NLS-1$
+    {
+      String name = element.getAttribute("name"); //$NON-NLS-1$
+      String value = element.getAttribute("value"); //$NON-NLS-1$
+      properties.put(prefix + name, value);
+      prefix += name + "."; //$NON-NLS-1$
+    }
+
+    if (levels > 0)
+    {
+      NodeList childNodes = element.getChildNodes();
+      for (int i = 0; i < childNodes.getLength(); i++)
+      {
+        Node childNode = childNodes.item(i);
+        if (childNode instanceof Element)
+        {
+          collectProperties((Element)childNode, prefix, properties, levels - 1);
+        }
+      }
+    }
+  }
+
+  private static <T> T createExecutableExtension(String extPointName, String elementName, String attributeName,
+      String type) throws CoreException
+  {
+    IExtensionRegistry registry = Platform.getExtensionRegistry();
+    IConfigurationElement[] elements = registry.getConfigurationElementsFor(OM.BUNDLE_ID, extPointName);
+    for (IConfigurationElement element : elements)
+    {
+      if (ObjectUtil.equals(element.getName(), elementName))
+      {
+        String storeType = element.getAttribute(attributeName);
+        if (ObjectUtil.equals(storeType, type))
+        {
+          @SuppressWarnings("unchecked")
+          T result = (T)element.createExecutableExtension("class"); //$NON-NLS-1$
+          return result;
+        }
+      }
+    }
+
+    return null;
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/RepositoryFactory.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/RepositoryFactory.java
new file mode 100644
index 0000000..58ea25c
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/RepositoryFactory.java
@@ -0,0 +1,45 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.spi.server;
+
+import org.eclipse.emf.cdo.internal.server.Repository;
+import org.eclipse.emf.cdo.server.IRepository;
+import org.eclipse.emf.cdo.server.IRepositoryFactory;
+
+import org.eclipse.net4j.util.container.IManagedContainer;
+
+/**
+ * @author Eike Stepper
+ * @since 2.0
+ */
+public class RepositoryFactory implements IRepositoryFactory
+{
+  public static final String TYPE = "default"; //$NON-NLS-1$
+
+  public RepositoryFactory()
+  {
+  }
+
+  public String getRepositoryType()
+  {
+    return TYPE;
+  }
+
+  public IRepository createRepository()
+  {
+    return new Repository.Default();
+  }
+
+  public static IRepository get(IManagedContainer container, String name)
+  {
+    return (IRepository)container.getElement(PRODUCT_GROUP, TYPE, name);
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/RepositoryUserManager.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/RepositoryUserManager.java
new file mode 100644
index 0000000..5b7d424
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/RepositoryUserManager.java
@@ -0,0 +1,147 @@
+/**

+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ * 

+ * Contributors:

+ *    Eike Stepper - initial API and implementation

+ */

+package org.eclipse.emf.cdo.spi.server;

+

+import org.eclipse.emf.cdo.server.CDOServerUtil;

+import org.eclipse.emf.cdo.server.IRepository;

+

+import org.eclipse.net4j.util.container.IElementProcessor;

+import org.eclipse.net4j.util.container.IManagedContainer;

+import org.eclipse.net4j.util.factory.ProductCreationException;

+import org.eclipse.net4j.util.lifecycle.Lifecycle;

+import org.eclipse.net4j.util.security.IUserManager;

+import org.eclipse.net4j.util.security.SecurityUtil;

+import org.eclipse.net4j.util.security.UserManagerFactory;

+

+/**

+ * @author Eike Stepper

+ * @since 4.0

+ */

+public abstract class RepositoryUserManager extends Lifecycle implements IUserManager

+{

+  private IManagedContainer container;

+

+  private String repositoryName;

+

+  protected RepositoryUserManager()

+  {

+  }

+

+  private void setContainer(IManagedContainer container)

+  {

+    this.container = container;

+  }

+

+  private void setRepositoryName(String repositoryName)

+  {

+    this.repositoryName = repositoryName;

+  }

+

+  public void addUser(String userID, char[] password)

+  {

+    // Cann be overridden in subclasses.

+  }

+

+  public void removeUser(String userID)

+  {

+    // Cann be overridden in subclasses.

+  }

+

+  public byte[] encrypt(String userID, byte[] data, String algorithmName, byte[] salt, int count)

+      throws SecurityException

+  {

+    IRepository repository = getRepository(container, repositoryName);

+    if (repository == null)

+    {

+      throw new SecurityException("Repository not found: " + repositoryName); //$NON-NLS-1$

+    }

+

+    char[] password = getPassword(repository, userID);

+    if (password == null)

+    {

+      throw new SecurityException("No such user: " + userID); //$NON-NLS-1$

+    }

+

+    try

+    {

+      return SecurityUtil.encrypt(data, password, algorithmName, salt, count);

+    }

+    catch (RuntimeException ex)

+    {

+      throw ex;

+    }

+    catch (Exception ex)

+    {

+      throw new SecurityException(ex);

+    }

+  }

+

+  protected IRepository getRepository(IManagedContainer container, String repositoryName)

+  {

+    return CDOServerUtil.getRepository(container, repositoryName);

+  }

+

+  protected abstract char[] getPassword(IRepository repository, String userID);

+

+  public static void prepareContainer(IManagedContainer container, RepositoryUserManagerFactory factory)

+  {

+    container.registerFactory(factory);

+    container.addPostProcessor(new RepositoryInjector());

+  }

+

+  /**

+   * @author Eike Stepper

+   */

+  public static abstract class RepositoryUserManagerFactory extends UserManagerFactory

+  {

+    protected RepositoryUserManagerFactory(String type)

+    {

+      super(type);

+    }

+

+    public final Object create(String description) throws ProductCreationException

+    {

+      RepositoryUserManager userManager = doCreate(description);

+      String repositoryName = getRepositoryName(description);

+      userManager.setRepositoryName(repositoryName);

+      return userManager;

+    }

+

+    protected String getRepositoryName(String description)

+    {

+      return description;

+    }

+

+    protected abstract RepositoryUserManager doCreate(String description) throws ProductCreationException;

+  }

+

+  /**

+   * @author Eike Stepper

+   */

+  public static class RepositoryInjector implements IElementProcessor

+  {

+    public RepositoryInjector()

+    {

+    }

+

+    public Object process(IManagedContainer container, String productGroup, String factoryType, String description,

+        Object element)

+    {

+      if (element instanceof RepositoryUserManager)

+      {

+        RepositoryUserManager userManager = (RepositoryUserManager)element;

+        userManager.setContainer(container);

+      }

+

+      return element;

+    }

+  }

+}

diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/Store.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/Store.java
new file mode 100644
index 0000000..407f50c
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/Store.java
@@ -0,0 +1,549 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.spi.server;
+
+import org.eclipse.emf.cdo.common.CDOCommonView;
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.id.CDOID.ObjectType;
+import org.eclipse.emf.cdo.common.id.CDOIDUtil;
+import org.eclipse.emf.cdo.common.revision.CDORevisionFactory;
+import org.eclipse.emf.cdo.internal.server.Repository;
+import org.eclipse.emf.cdo.server.IRepository;
+import org.eclipse.emf.cdo.server.ISession;
+import org.eclipse.emf.cdo.server.ISessionManager;
+import org.eclipse.emf.cdo.server.IStoreAccessor;
+import org.eclipse.emf.cdo.server.ITransaction;
+import org.eclipse.emf.cdo.server.IView;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+
+import org.eclipse.net4j.util.ReflectUtil.ExcludeFromDump;
+import org.eclipse.net4j.util.StringUtil;
+import org.eclipse.net4j.util.container.IContainerDelta.Kind;
+import org.eclipse.net4j.util.lifecycle.Lifecycle;
+import org.eclipse.net4j.util.lifecycle.LifecycleUtil;
+import org.eclipse.net4j.util.om.monitor.ProgressDistributor;
+
+import org.eclipse.emf.ecore.EClass;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author Eike Stepper
+ * @since 2.0
+ */
+public abstract class Store extends Lifecycle implements InternalStore
+{
+  /**
+   * @since 3.0
+   * @deprecated Use CDOBranchPoint.UNSPECIFIED_DATE
+   */
+  @Deprecated
+  public static final long UNSPECIFIED_DATE = CDOBranchPoint.UNSPECIFIED_DATE;
+
+  private String type;
+
+  private Set<ObjectType> objectIDTypes;
+
+  private Set<ChangeFormat> supportedChangeFormats;
+
+  private Set<RevisionTemporality> supportedRevisionTemporalities;
+
+  private Set<RevisionParallelism> supportedRevisionParallelisms;
+
+  private RevisionTemporality revisionTemporality = RevisionTemporality.NONE;
+
+  private RevisionParallelism revisionParallelism = RevisionParallelism.NONE;
+
+  private InternalRepository repository;
+
+  private boolean dropAllDataOnActivate;
+
+  /**
+   * Is protected against concurrent thread access through {@link Repository#createBranchLock}.
+   */
+  @ExcludeFromDump
+  private transient int lastBranchID;
+
+  /**
+   * Is protected against concurrent thread access through {@link Repository#createBranchLock}.
+   */
+  @ExcludeFromDump
+  private transient int lastLocalBranchID;
+
+  @ExcludeFromDump
+  private transient long lastCommitTime;
+
+  @ExcludeFromDump
+  private transient Object lastCommitTimeLock = new Object();
+
+  @ExcludeFromDump
+  private transient long lastNonLocalCommitTime;
+
+  @ExcludeFromDump
+  private transient Object lastNonLocalCommitTimeLock = new Object();
+
+  /**
+   * @since 3.0
+   */
+  @ExcludeFromDump
+  private transient ProgressDistributor indicatingCommitDistributor = new ProgressDistributor.Geometric()
+  {
+    @Override
+    public String toString()
+    {
+      String result = "indicatingCommitDistributor"; //$NON-NLS-1$
+      if (repository != null)
+      {
+        result += ": " + repository.getName(); //$NON-NLS-1$
+      }
+
+      return result;
+    }
+  };
+
+  /**
+   * @since 3.0
+   */
+  public Store(String type, Set<CDOID.ObjectType> objectIDTypes, Set<ChangeFormat> supportedChangeFormats,
+      Set<RevisionTemporality> supportedRevisionTemporalities, Set<RevisionParallelism> supportedRevisionParallelisms)
+  {
+    checkArg(!StringUtil.isEmpty(type), "Empty type"); //$NON-NLS-1$
+    this.type = type;
+    this.objectIDTypes = objectIDTypes;
+
+    checkArg(supportedChangeFormats != null && !supportedChangeFormats.isEmpty(), "Empty supportedChangeFormats"); //$NON-NLS-1$
+    this.supportedChangeFormats = supportedChangeFormats;
+
+    checkArg(supportedRevisionTemporalities != null && !supportedRevisionTemporalities.isEmpty(),
+        "Empty supportedRevisionTemporalities"); //$NON-NLS-1$
+    this.supportedRevisionTemporalities = supportedRevisionTemporalities;
+
+    checkArg(supportedRevisionParallelisms != null && !supportedRevisionParallelisms.isEmpty(),
+        "Empty supportedRevisionParallelisms"); //$NON-NLS-1$
+    this.supportedRevisionParallelisms = supportedRevisionParallelisms;
+  }
+
+  public final String getType()
+  {
+    return type;
+  }
+
+  /**
+   * @since 3.0
+   */
+  public Set<CDOID.ObjectType> getObjectIDTypes()
+  {
+    return objectIDTypes;
+  }
+
+  /**
+   * @since 4.0
+   */
+  protected void setObjectIDTypes(Set<ObjectType> objectIDTypes)
+  {
+    this.objectIDTypes = objectIDTypes;
+  }
+
+  public Set<ChangeFormat> getSupportedChangeFormats()
+  {
+    return supportedChangeFormats;
+  }
+
+  public Set<RevisionTemporality> getSupportedRevisionTemporalities()
+  {
+    return supportedRevisionTemporalities;
+  }
+
+  public final Set<RevisionParallelism> getSupportedRevisionParallelisms()
+  {
+    return supportedRevisionParallelisms;
+  }
+
+  public RevisionTemporality getRevisionTemporality()
+  {
+    return revisionTemporality;
+  }
+
+  public void setRevisionTemporality(RevisionTemporality revisionTemporality)
+  {
+    checkInactive();
+    checkState(supportedRevisionTemporalities.contains(revisionTemporality), "Revision temporality not supported: " //$NON-NLS-1$
+        + revisionTemporality);
+    this.revisionTemporality = revisionTemporality;
+  }
+
+  public RevisionParallelism getRevisionParallelism()
+  {
+    return revisionParallelism;
+  }
+
+  public void setRevisionParallelism(RevisionParallelism revisionParallelism)
+  {
+    checkInactive();
+    checkState(supportedRevisionParallelisms.contains(revisionParallelism), "Revision parallelism not supported: " //$NON-NLS-1$
+        + revisionParallelism);
+    this.revisionParallelism = revisionParallelism;
+  }
+
+  /**
+   * @since 3.0
+   */
+  public InternalRepository getRepository()
+  {
+    return repository;
+  }
+
+  public void setRepository(IRepository repository)
+  {
+    this.repository = (InternalRepository)repository;
+  }
+
+  /**
+   * @since 4.0
+   */
+  public boolean isDropAllDataOnActivate()
+  {
+    return dropAllDataOnActivate;
+  }
+
+  /**
+   * @since 4.0
+   */
+  public void setDropAllDataOnActivate(boolean dropAllDataOnActivate)
+  {
+    this.dropAllDataOnActivate = dropAllDataOnActivate;
+  }
+
+  /**
+   * @since 3.0
+   */
+  public int getLastBranchID()
+  {
+    return lastBranchID;
+  }
+
+  /**
+   * @since 3.0
+   */
+  public void setLastBranchID(int lastBranchID)
+  {
+    this.lastBranchID = lastBranchID;
+  }
+
+  /**
+   * @since 3.0
+   */
+  public int getNextBranchID()
+  {
+    return ++lastBranchID;
+  }
+
+  /**
+   * @since 3.0
+   */
+  public int getLastLocalBranchID()
+  {
+    return lastLocalBranchID;
+  }
+
+  /**
+   * @since 3.0
+   */
+  public void setLastLocalBranchID(int lastLocalBranchID)
+  {
+    this.lastLocalBranchID = lastLocalBranchID;
+  }
+
+  /**
+   * @since 3.0
+   */
+  public int getNextLocalBranchID()
+  {
+    return --lastLocalBranchID;
+  }
+
+  /**
+   * @since 3.0
+   */
+  public long getLastCommitTime()
+  {
+    synchronized (lastCommitTimeLock)
+    {
+      return lastCommitTime;
+    }
+  }
+
+  /**
+   * @since 3.0
+   */
+  public void setLastCommitTime(long lastCommitTime)
+  {
+    synchronized (lastCommitTimeLock)
+    {
+      if (this.lastCommitTime < lastCommitTime)
+      {
+        this.lastCommitTime = lastCommitTime;
+      }
+    }
+  }
+
+  /**
+   * @since 3.0
+   */
+  public long getLastNonLocalCommitTime()
+  {
+    synchronized (lastNonLocalCommitTimeLock)
+    {
+      return lastNonLocalCommitTime;
+    }
+  }
+
+  /**
+   * @since 3.0
+   */
+  public void setLastNonLocalCommitTime(long lastNonLocalCommitTime)
+  {
+    synchronized (lastNonLocalCommitTimeLock)
+    {
+      if (this.lastNonLocalCommitTime < lastNonLocalCommitTime)
+      {
+        this.lastNonLocalCommitTime = lastNonLocalCommitTime;
+      }
+    }
+  }
+
+  public IStoreAccessor getReader(ISession session)
+  {
+    IStoreAccessor reader = null;
+    StoreAccessorPool pool = getReaderPool(session, false);
+    if (pool != null)
+    {
+      reader = pool.removeStoreAccessor(session);
+    }
+
+    if (reader == null && session != null)
+    {
+      CDOCommonView[] views = session.getViews();
+      for (CDOCommonView view : views)
+      {
+        pool = getWriterPool((IView)view, false);
+        if (pool != null)
+        {
+          reader = pool.removeStoreAccessor(view);
+          if (reader != null)
+          {
+            break;
+          }
+        }
+      }
+    }
+
+    if (reader == null)
+    {
+      reader = createReader(session);
+      LifecycleUtil.activate(reader);
+    }
+
+    return reader;
+  }
+
+  public IStoreAccessor getWriter(ITransaction transaction)
+  {
+    IStoreAccessor writer = null;
+    StoreAccessorPool pool = getWriterPool(transaction, false);
+    if (pool != null)
+    {
+      writer = pool.removeStoreAccessor(transaction);
+    }
+
+    if (writer == null)
+    {
+      writer = createWriter(transaction);
+      LifecycleUtil.activate(writer);
+    }
+
+    return writer;
+  }
+
+  public ProgressDistributor getIndicatingCommitDistributor()
+  {
+    return indicatingCommitDistributor;
+  }
+
+  /**
+   * @since 3.0
+   */
+  public InternalCDORevision createRevision(EClass eClass, CDOID id)
+  {
+    CDORevisionFactory factory = repository.getRevisionManager().getFactory();
+    InternalCDORevision revision = (InternalCDORevision)factory.createRevision(eClass);
+    revision.setID(id);
+    return revision;
+  }
+
+  /**
+   * @since 4.0
+   */
+  protected void releaseAccessor(StoreAccessorBase accessor)
+  {
+    StoreAccessorPool pool = null;
+    if (accessor.isReader())
+    {
+      pool = getReaderPool(accessor.getSession(), true);
+    }
+    else
+    {
+      pool = getWriterPool(accessor.getTransaction(), true);
+    }
+
+    if (pool != null)
+    {
+      pool.addStoreAccessor(accessor);
+    }
+    else
+    {
+      accessor.deactivate();
+    }
+  }
+
+  /**
+   * Returns a {@link StoreAccessorPool pool} that may contain {@link IStoreAccessor} instances that are compatible with
+   * the given session. The implementor may return <code>null</code> to indicate that no pooling occurs. It's also left
+   * to the implementors choice how to determine the appropriate pool instance to be used for the given session, for
+   * example it could always return the same pool instance, regardless of the given session.
+   * <p>
+   * If the implementor of this method decides to create pools that are only compatible with certain sessions or views,
+   * then it is his responsibility to listen to {@link Kind#REMOVED REMOVED} events sent by either the
+   * {@link ISessionManager} (indicating that a session is closed) or any of its sessions (indicating that a view is
+   * closed). <b>Note:</b> Closing a session <em>implies</em> that all contained views are closed sliently without
+   * firing respective events!
+   * 
+   * @param session
+   *          The context which the pool must be compatible with. Must not be <code>null</code>.
+   * @param forReleasing
+   *          Enables lazy pool creation. The implementor is not supposed to create a new pool if <code>false</code> is
+   *          passed. If <code>true</code> is passed it's up to the implementor whether to create a new pool or not.
+   */
+  protected abstract StoreAccessorPool getReaderPool(ISession session, boolean forReleasing);
+
+  /**
+   * Returns a {@link StoreAccessorPool pool} that may contain {@link IStoreAccessor} instances that are compatible with
+   * the given session. The implementor may return <code>null</code> to indicate that no pooling occurs. It's also left
+   * to the implementors choice how to determine the appropriate pool instance to be used for the given session, for
+   * example it could always return the same pool instance, regardless of the given session.
+   * <p>
+   * If the implementor of this method decides to create pools that are only compatible with certain sessions or views,
+   * then it is his responsibility to listen to {@link Kind#REMOVED REMOVED} events sent by either the
+   * {@link ISessionManager} (indicating that a session is closed) or any of its sessions (indicating that a view is
+   * closed). <b>Note:</b> Closing a session <em>implies</em> that all contained views are closed sliently without
+   * firing respective events!
+   * 
+   * @param view
+   *          The context which the pool must be compatible with. Must not be <code>null</code>.
+   * @param forReleasing
+   *          Enables lazy pool creation. The implementor is not supposed to create a new pool if <code>false</code> is
+   *          passed. If <code>true</code> is passed it's up to the implementor whether to create a new pool or not.
+   */
+  protected abstract StoreAccessorPool getWriterPool(IView view, boolean forReleasing);
+
+  /**
+   * Creates and returns a <b>new</b> {@link IStoreAccessor} instance. The caller of this method is responsible for
+   * {@link Lifecycle#activate() activating} the new instance.
+   */
+  protected abstract IStoreAccessor createReader(ISession session);
+
+  /**
+   * Creates and returns a <b>new</b> {@link IStoreAccessor} instance. The caller of this method is responsible for
+   * {@link Lifecycle#activate() activating} the new instance.
+   */
+  protected abstract IStoreAccessor createWriter(ITransaction transaction);
+
+  protected static <T> Set<T> set(T... elements)
+  {
+    return Collections.unmodifiableSet(new HashSet<T>(Arrays.asList(elements)));
+  }
+
+  /**
+   * @since 4.0
+   */
+  public static String idToString(CDOID id)
+  {
+    StringBuilder builder = new StringBuilder();
+    CDOIDUtil.write(builder, id);
+    return builder.toString();
+  }
+
+  /**
+   * @since 4.0
+   */
+  public static CDOID stringToID(String string)
+  {
+    return CDOIDUtil.read(string);
+  }
+
+  /**
+   * @since 3.0
+   */
+  public static IStoreAccessor.QueryResourcesContext.ExactMatch createExactMatchContext(final CDOID folderID,
+      final String name, final CDOBranchPoint branchPoint)
+  {
+    return new IStoreAccessor.QueryResourcesContext.ExactMatch()
+    {
+      private CDOID resourceID;
+
+      public CDOID getResourceID()
+      {
+        return resourceID;
+      }
+
+      public CDOBranch getBranch()
+      {
+        return branchPoint.getBranch();
+      }
+
+      public long getTimeStamp()
+      {
+        return branchPoint.getTimeStamp();
+      }
+
+      public CDOID getFolderID()
+      {
+        return folderID;
+      }
+
+      public String getName()
+      {
+        return name;
+      }
+
+      public boolean exactMatch()
+      {
+        return true;
+      }
+
+      public int getMaxResults()
+      {
+        return 1;
+      }
+
+      public boolean addResource(CDOID resourceID)
+      {
+        this.resourceID = resourceID;
+        return false;
+      }
+    };
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/StoreAccessor.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/StoreAccessor.java
new file mode 100644
index 0000000..5b988af
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/StoreAccessor.java
@@ -0,0 +1,180 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Simon McDuff - bug 201266
+ *    Simon McDuff - bug 213402
+ */
+package org.eclipse.emf.cdo.spi.server;
+
+import org.eclipse.emf.cdo.common.CDOCommonRepository.IDGenerationLocation;
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.server.ISession;
+import org.eclipse.emf.cdo.server.IStore;
+import org.eclipse.emf.cdo.server.ITransaction;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionDelta;
+
+import org.eclipse.net4j.util.WrappedException;
+import org.eclipse.net4j.util.io.ExtendedDataInputStream;
+import org.eclipse.net4j.util.io.LimitedInputStream;
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+
+/**
+ * @author Eike Stepper
+ * @since 2.0
+ */
+public abstract class StoreAccessor extends StoreAccessorBase
+{
+  protected StoreAccessor(Store store, ISession session)
+  {
+    super(store, session);
+  }
+
+  protected StoreAccessor(Store store, ITransaction transaction)
+  {
+    super(store, transaction);
+  }
+
+  /**
+   * @since 4.0
+   */
+  @Override
+  protected void doWrite(InternalCommitContext context, OMMonitor monitor)
+  {
+    CDOBranch branch = context.getBranchPoint().getBranch();
+    long timeStamp = context.getBranchPoint().getTimeStamp();
+    long previousTimeStamp = context.getPreviousTimeStamp();
+    String userID = context.getUserID();
+    String commitComment = context.getCommitComment();
+
+    boolean deltas = getStore().getSupportedChangeFormats().contains(IStore.ChangeFormat.DELTA);
+
+    InternalCDOPackageUnit[] newPackageUnits = context.getNewPackageUnits();
+    InternalCDORevision[] newObjects = context.getNewObjects();
+    CDOID[] detachedObjects = context.getDetachedObjects();
+    int dirtyCount = deltas ? context.getDirtyObjectDeltas().length : context.getDirtyObjects().length;
+
+    try
+    {
+      monitor.begin(1 + newPackageUnits.length + 2 + newObjects.length + detachedObjects.length + dirtyCount);
+      writeCommitInfo(branch, timeStamp, previousTimeStamp, userID, commitComment, monitor.fork());
+
+      if (newPackageUnits.length != 0)
+      {
+        writePackageUnits(newPackageUnits, monitor.fork(newPackageUnits.length));
+      }
+
+      if (getStore().getRepository().getIDGenerationLocation() == IDGenerationLocation.STORE)
+      {
+        addIDMappings(context, monitor.fork());
+      }
+
+      applyIDMappings(context, monitor);
+
+      if (detachedObjects.length != 0)
+      {
+        detachObjects(detachedObjects, branch, timeStamp, monitor.fork(detachedObjects.length));
+      }
+
+      if (newObjects.length != 0)
+      {
+        writeRevisions(newObjects, branch, monitor.fork(newObjects.length));
+      }
+
+      if (dirtyCount != 0)
+      {
+        if (deltas)
+        {
+          writeRevisionDeltas(context.getDirtyObjectDeltas(), branch, timeStamp, monitor.fork(dirtyCount));
+        }
+        else
+        {
+          writeRevisions(context.getDirtyObjects(), branch, monitor.fork(dirtyCount));
+        }
+      }
+
+      ExtendedDataInputStream in = context.getLobs();
+      if (in != null)
+      {
+        try
+        {
+          int count = in.readInt();
+          for (int i = 0; i < count; i++)
+          {
+            byte[] id = in.readByteArray();
+            long size = in.readLong();
+            if (size > 0)
+            {
+              writeBlob(id, size, new LimitedInputStream(in, size));
+            }
+            else
+            {
+              writeClob(id, -size, new InputStreamReader(new LimitedInputStream(in, -size)));
+            }
+          }
+        }
+        catch (IOException ex)
+        {
+          throw WrappedException.wrap(ex);
+        }
+      }
+    }
+    finally
+    {
+      monitor.done();
+    }
+  }
+
+  /**
+   * @since 3.0
+   */
+  protected void applyIDMappings(InternalCommitContext context, OMMonitor monitor)
+  {
+    context.applyIDMappings(monitor.fork());
+  }
+
+  /**
+   * @since 4.0
+   */
+  protected abstract void writeCommitInfo(CDOBranch branch, long timeStamp, long previousTimeStamp, String userID,
+      String comment, OMMonitor monitor);
+
+  /**
+   * @since 3.0
+   */
+  protected abstract void writeRevisions(InternalCDORevision[] revisions, CDOBranch branch, OMMonitor monitor);
+
+  /**
+   * @since 3.0
+   */
+  protected abstract void writeRevisionDeltas(InternalCDORevisionDelta[] revisionDeltas, CDOBranch branch,
+      long created, OMMonitor monitor);
+
+  /**
+   * @since 3.0
+   */
+  protected abstract void detachObjects(CDOID[] detachedObjects, CDOBranch branch, long timeStamp, OMMonitor monitor);
+
+  /**
+   * @since 4.0
+   */
+  protected abstract void writeBlob(byte[] id, long size, InputStream inputStream) throws IOException;
+
+  /**
+   * @since 4.0
+   */
+  protected abstract void writeClob(byte[] id, long size, Reader reader) throws IOException;
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/StoreAccessorBase.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/StoreAccessorBase.java
new file mode 100644
index 0000000..7be7a2a
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/StoreAccessorBase.java
@@ -0,0 +1,508 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ *    Simon McDuff - bug 201266
+ *    Simon McDuff - bug 213402
+ */
+package org.eclipse.emf.cdo.spi.server;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
+import org.eclipse.emf.cdo.common.branch.CDOBranchVersion;
+import org.eclipse.emf.cdo.common.commit.CDOCommitData;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.id.CDOIDTemp;
+import org.eclipse.emf.cdo.common.id.CDOIDUtil;
+import org.eclipse.emf.cdo.common.model.CDOPackageUnit;
+import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion;
+import org.eclipse.emf.cdo.common.revision.CDOList;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.common.revision.CDORevisionHandler;
+import org.eclipse.emf.cdo.common.revision.CDORevisionKey;
+import org.eclipse.emf.cdo.common.revision.delta.CDOAddFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOClearFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDORemoveFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOSetFeatureDelta;
+import org.eclipse.emf.cdo.common.revision.delta.CDOUnsetFeatureDelta;
+import org.eclipse.emf.cdo.common.util.CDOCommonUtil;
+import org.eclipse.emf.cdo.internal.common.commit.CDOCommitDataImpl;
+import org.eclipse.emf.cdo.internal.server.bundle.OM;
+import org.eclipse.emf.cdo.server.ISession;
+import org.eclipse.emf.cdo.server.IStoreAccessor;
+import org.eclipse.emf.cdo.server.ITransaction;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry;
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit;
+import org.eclipse.emf.cdo.spi.common.revision.CDOFeatureDeltaVisitorImpl;
+import org.eclipse.emf.cdo.spi.common.revision.DetachedCDORevision;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionDelta;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager;
+
+import org.eclipse.net4j.util.lifecycle.Lifecycle;
+import org.eclipse.net4j.util.om.monitor.OMMonitor;
+import org.eclipse.net4j.util.om.trace.ContextTracer;
+
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * @author Eike Stepper
+ * @since 4.0
+ */
+public abstract class StoreAccessorBase extends Lifecycle implements IStoreAccessor
+{
+  private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG, StoreAccessorBase.class);
+
+  private Store store;
+
+  private Object context;
+
+  private boolean reader;
+
+  private List<CommitContext> commitContexts = new ArrayList<CommitContext>();
+
+  private StoreAccessorBase(Store store, Object context, boolean reader)
+  {
+    this.store = store;
+    this.context = context;
+    this.reader = reader;
+  }
+
+  protected StoreAccessorBase(Store store, ISession session)
+  {
+    this(store, session, true);
+  }
+
+  protected StoreAccessorBase(Store store, ITransaction transaction)
+  {
+    this(store, transaction, false);
+  }
+
+  void setContext(Object context)
+  {
+    this.context = context;
+  }
+
+  public Store getStore()
+  {
+    return store;
+  }
+
+  public boolean isReader()
+  {
+    return reader;
+  }
+
+  /**
+   * @since 3.0
+   */
+  public InternalSession getSession()
+  {
+    if (context instanceof ITransaction)
+    {
+      return (InternalSession)((ITransaction)context).getSession();
+    }
+
+    return (InternalSession)context;
+  }
+
+  public ITransaction getTransaction()
+  {
+    if (context instanceof ITransaction)
+    {
+      return (ITransaction)context;
+    }
+
+    return null;
+  }
+
+  public void release()
+  {
+    store.releaseAccessor(this);
+    commitContexts.clear();
+  }
+
+  /**
+   * @since 3.0
+   */
+  public final void write(InternalCommitContext context, OMMonitor monitor)
+  {
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Writing transaction: {0}", getTransaction()); //$NON-NLS-1$
+    }
+
+    commitContexts.add(context);
+    doWrite(context, monitor);
+  }
+
+  protected abstract void doWrite(InternalCommitContext context, OMMonitor monitor);
+
+  /**
+   * @since 3.0
+   */
+  public final void commit(OMMonitor monitor)
+  {
+    doCommit(monitor);
+
+    long latest = CDORevision.UNSPECIFIED_DATE;
+    long latestNonLocal = CDORevision.UNSPECIFIED_DATE;
+    for (CommitContext commitContext : commitContexts)
+    {
+      CDOBranchPoint branchPoint = commitContext.getBranchPoint();
+      long timeStamp = branchPoint.getTimeStamp();
+      if (timeStamp > latest)
+      {
+        latest = timeStamp;
+      }
+
+      CDOBranch branch = branchPoint.getBranch();
+      if (!branch.isLocal())
+      {
+        if (timeStamp > latestNonLocal)
+        {
+          latestNonLocal = timeStamp;
+        }
+      }
+    }
+
+    getStore().setLastCommitTime(latest);
+    getStore().setLastNonLocalCommitTime(latestNonLocal);
+  }
+
+  /**
+   * @since 3.0
+   */
+  protected abstract void doCommit(OMMonitor monitor);
+
+  public final void rollback()
+  {
+    if (TRACER.isEnabled())
+    {
+      TRACER.format("Rolling back transaction: {0}", getTransaction()); //$NON-NLS-1$
+    }
+
+    for (CommitContext commitContext : commitContexts)
+    {
+      doRollback(commitContext);
+    }
+  }
+
+  protected abstract void doRollback(CommitContext commitContext);
+
+  /**
+   * @since 3.0
+   */
+  public CDOID readResourceID(CDOID folderID, String name, CDOBranchPoint branchPoint)
+  {
+    QueryResourcesContext.ExactMatch context = Store.createExactMatchContext(folderID, name, branchPoint);
+    queryResources(context);
+    return context.getResourceID();
+  }
+
+  /**
+   * @since 3.0
+   */
+  public CDOCommitData loadCommitData(long timeStamp)
+  {
+    CommitDataRevisionHandler handler = new CommitDataRevisionHandler(this, timeStamp);
+    return handler.getCommitData();
+  }
+
+  /**
+   * Add ID mappings for all new objects of a transaction to the commit context. The implementor must, for each new
+   * object of the commit context, determine a permanent CDOID and make it known to the context by calling
+   * {@link InternalCommitContext#addIDMapping(CDOID, CDOID)}.
+   * 
+   * @since 3.0
+   */
+  public void addIDMappings(InternalCommitContext commitContext, OMMonitor monitor)
+  {
+    try
+    {
+      CDORevision[] newObjects = commitContext.getNewObjects();
+      monitor.begin(newObjects.length);
+      for (CDORevision revision : newObjects)
+      {
+        CDOID id = revision.getID();
+        if (id instanceof CDOIDTemp)
+        {
+          CDOIDTemp oldID = (CDOIDTemp)id;
+          CDOID newID = getNextCDOID(revision);
+          if (CDOIDUtil.isNull(newID) || newID.isTemporary())
+          {
+            throw new IllegalStateException("newID=" + newID); //$NON-NLS-1$
+          }
+
+          commitContext.addIDMapping(oldID, newID);
+        }
+
+        monitor.worked();
+      }
+    }
+    finally
+    {
+      monitor.done();
+    }
+  }
+
+  protected abstract CDOID getNextCDOID(CDORevision revision);
+
+  protected void doPassivate() throws Exception
+  {
+  }
+
+  protected void doUnpassivate() throws Exception
+  {
+  }
+
+  /**
+   * @author Eike Stepper
+   * @since 3.0
+   */
+  public static class CommitDataRevisionHandler implements CDORevisionHandler
+  {
+    private IStoreAccessor storeAccessor;
+
+    private long timeStamp;
+
+    private InternalCDORevisionManager revisionManager;
+
+    private List<CDOPackageUnit> newPackageUnits = new ArrayList<CDOPackageUnit>();
+
+    private List<CDOIDAndVersion> newObjects = new ArrayList<CDOIDAndVersion>();
+
+    private List<CDORevisionKey> changedObjects = new ArrayList<CDORevisionKey>();
+
+    private DetachCounter detachCounter = new DetachCounter();
+
+    public CommitDataRevisionHandler(IStoreAccessor storeAccessor, long timeStamp)
+    {
+      this.storeAccessor = storeAccessor;
+      this.timeStamp = timeStamp;
+
+      InternalStore store = (InternalStore)storeAccessor.getStore();
+      InternalRepository repository = store.getRepository();
+      revisionManager = repository.getRevisionManager();
+
+      InternalCDOPackageRegistry packageRegistry = repository.getPackageRegistry(false);
+      InternalCDOPackageUnit[] packageUnits = packageRegistry.getPackageUnits(timeStamp, timeStamp);
+      for (InternalCDOPackageUnit packageUnit : packageUnits)
+      {
+        if (!packageUnit.isSystem())
+        {
+          newPackageUnits.add(packageUnit);
+        }
+      }
+    }
+
+    public CDOCommitData getCommitData()
+    {
+      storeAccessor.handleRevisions(null, null, timeStamp, true, new CDORevisionHandler.Filtered.Undetached(this));
+
+      List<CDOIDAndVersion> detachedObjects = detachCounter.getDetachedObjects();
+      return new CDOCommitDataImpl(newPackageUnits, newObjects, changedObjects, detachedObjects);
+    }
+
+    /**
+     * @since 4.0
+     */
+    public boolean handleRevision(CDORevision rev)
+    {
+      if (rev.getTimeStamp() != timeStamp)
+      {
+        throw new IllegalArgumentException("Invalid revision time stamp: "
+            + CDOCommonUtil.formatTimeStamp(rev.getTimeStamp()));
+      }
+
+      if (rev instanceof DetachedCDORevision)
+      {
+        // Do nothing. Detached objects are handled by detachCounter.
+      }
+      else
+      {
+        InternalCDORevision revision = (InternalCDORevision)rev;
+        CDOID id = revision.getID();
+        CDOBranch branch = revision.getBranch();
+        int version = revision.getVersion();
+        if (version > CDOBranchVersion.FIRST_VERSION)
+        {
+          CDOBranchVersion oldVersion = branch.getVersion(version - 1);
+          InternalCDORevision oldRevision = revisionManager.getRevisionByVersion(id, oldVersion, CDORevision.UNCHUNKED,
+              true);
+          InternalCDORevisionDelta delta = revision.compare(oldRevision);
+          changedObjects.add(delta);
+
+          detachCounter.update(oldRevision, delta);
+        }
+        else
+        {
+          InternalCDORevision oldRevision = getRevisionFromBase(id, branch);
+          if (oldRevision != null)
+          {
+            InternalCDORevisionDelta delta = revision.compare(oldRevision);
+            changedObjects.add(delta);
+          }
+          else
+          {
+            InternalCDORevision newRevision = revision.copy();
+            newRevision.setRevised(CDOBranchPoint.UNSPECIFIED_DATE);
+            newObjects.add(newRevision);
+          }
+        }
+      }
+
+      return true;
+    }
+
+    private InternalCDORevision getRevisionFromBase(CDOID id, CDOBranch branch)
+    {
+      if (branch.isMainBranch())
+      {
+        return null;
+      }
+
+      CDOBranchPoint base = branch.getBase();
+      InternalCDORevision revision = revisionManager.getRevision(id, base, CDORevision.UNCHUNKED,
+          CDORevision.DEPTH_NONE, true);
+      if (revision == null)
+      {
+        revision = getRevisionFromBase(id, base.getBranch());
+      }
+
+      return revision;
+    }
+
+    /**
+     * @author Eike Stepper
+     */
+    private static final class DetachCounter extends CDOFeatureDeltaVisitorImpl
+    {
+      private Map<CDOID, AtomicInteger> counters = new HashMap<CDOID, AtomicInteger>();
+
+      private InternalCDORevision oldRevision;
+
+      public DetachCounter()
+      {
+      }
+
+      public void update(InternalCDORevision oldRevision, InternalCDORevisionDelta delta)
+      {
+        try
+        {
+          this.oldRevision = oldRevision;
+          delta.accept(this);
+        }
+        finally
+        {
+          this.oldRevision = null;
+        }
+      }
+
+      public List<CDOIDAndVersion> getDetachedObjects()
+      {
+        List<CDOIDAndVersion> result = new ArrayList<CDOIDAndVersion>();
+        for (Entry<CDOID, AtomicInteger> entry : counters.entrySet())
+        {
+          int value = entry.getValue().get();
+          if (value == -1)
+          {
+            CDOID id = entry.getKey();
+            result.add(CDOIDUtil.createIDAndVersion(id, CDOBranchVersion.UNSPECIFIED_VERSION));
+          }
+        }
+
+        return result;
+      }
+
+      @Override
+      public void visit(CDOAddFeatureDelta delta)
+      {
+        if (isContainment(delta.getFeature()))
+        {
+          handleContainment(delta.getValue(), 1);
+        }
+      }
+
+      @Override
+      public void visit(CDORemoveFeatureDelta delta)
+      {
+        if (isContainment(delta.getFeature()))
+        {
+          handleContainment(delta.getValue(), -1);
+        }
+      }
+
+      @Override
+      public void visit(CDOSetFeatureDelta delta)
+      {
+        if (isContainment(delta.getFeature()))
+        {
+          handleContainment(delta.getValue(), 1);
+        }
+      }
+
+      @Override
+      public void visit(CDOUnsetFeatureDelta delta)
+      {
+        EStructuralFeature feature = delta.getFeature();
+        if (isContainment(feature))
+        {
+          Object value = oldRevision.getValue(feature);
+          handleContainment(value, -1);
+        }
+      }
+
+      @Override
+      public void visit(CDOClearFeatureDelta delta)
+      {
+        EStructuralFeature feature = delta.getFeature();
+        if (isContainment(feature))
+        {
+          CDOList list = oldRevision.getList(feature);
+          for (Object value : list)
+          {
+            handleContainment(value, -1);
+          }
+        }
+      }
+
+      private void handleContainment(Object value, int delta)
+      {
+        CDOID id = (CDOID)value;
+        AtomicInteger counter = counters.get(id);
+        if (counter == null)
+        {
+          counter = new AtomicInteger();
+          counters.put(id, counter);
+        }
+
+        counter.addAndGet(delta);
+      }
+
+      private static boolean isContainment(EStructuralFeature feature)
+      {
+        if (feature instanceof EReference)
+        {
+          EReference reference = (EReference)feature;
+          return reference.isContainment();
+        }
+
+        return false;
+      }
+    }
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/StoreAccessorPool.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/StoreAccessorPool.java
new file mode 100644
index 0000000..4b71389
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/StoreAccessorPool.java
@@ -0,0 +1,121 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.spi.server;
+
+import org.eclipse.emf.cdo.internal.server.bundle.OM;
+import org.eclipse.emf.cdo.server.ISession;
+import org.eclipse.emf.cdo.server.IStore;
+import org.eclipse.emf.cdo.server.IView;
+
+import org.eclipse.net4j.util.lifecycle.LifecycleUtil;
+import org.eclipse.net4j.util.om.log.OMLogger;
+
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+/**
+ * @author Eike Stepper
+ * @since 2.0
+ */
+public class StoreAccessorPool
+{
+  /**
+   * The {@link IStore store} instance that manages this pool.
+   */
+  private IStore store;
+
+  /**
+   * The pooling context of this pool. An instance of either {@link ISession} or {@link IView}, or <code>null</code> if
+   * this pool is not contextual.
+   */
+  private Object context;
+
+  private ConcurrentLinkedQueue<StoreAccessorBase> accessors = new ConcurrentLinkedQueue<StoreAccessorBase>();
+
+  public StoreAccessorPool(IStore store, Object context)
+  {
+    this.store = store;
+    this.context = context;
+  }
+
+  public IStore getStore()
+  {
+    return store;
+  }
+
+  public Object getContext()
+  {
+    return context;
+  }
+
+  /**
+   * Passivates the given {@link StoreAccessor store accessor} and adds it to this pool.
+   * 
+   * @since 4.0
+   */
+  public void addStoreAccessor(StoreAccessorBase storeAccessor)
+  {
+    try
+    {
+      storeAccessor.doPassivate();
+      accessors.add(storeAccessor);
+    }
+    catch (Exception ex)
+    {
+      OM.LOG.error(ex);
+    }
+  }
+
+  /**
+   * Returns a {@link StoreAccessor store accessor} from this pool if one is available, or <code>null</code> otherwise.
+   * If a store accessor is available it is removed from this pool and its unpassivate method is called.
+   * 
+   * @since 4.0
+   */
+  public StoreAccessorBase removeStoreAccessor(Object context)
+  {
+    StoreAccessorBase accessor = accessors.poll();
+    if (accessor != null)
+    {
+      try
+      {
+        accessor.doUnpassivate();
+        accessor.setContext(context);
+      }
+      catch (Exception ex)
+      {
+        OM.LOG.error(ex);
+        return null;
+      }
+    }
+
+    return accessor;
+  }
+
+  /**
+   * Deactivates all contained {@link StoreAccessor store accessors} and clears this pool.
+   */
+  public void dispose()
+  {
+    for (;;)
+    {
+      StoreAccessorBase accessor = accessors.poll();
+      if (accessor == null)
+      {
+        break;
+      }
+
+      LifecycleUtil.deactivate(accessor, OMLogger.Level.WARN);
+    }
+
+    context = null;
+    store = null;
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/StoreChunkReader.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/StoreChunkReader.java
new file mode 100644
index 0000000..36b7dc1
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/StoreChunkReader.java
@@ -0,0 +1,72 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.spi.server;
+
+import org.eclipse.emf.cdo.common.revision.CDORevision;
+import org.eclipse.emf.cdo.server.IStoreAccessor;
+import org.eclipse.emf.cdo.server.IStoreChunkReader;
+
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Eike Stepper
+ * @since 2.0
+ */
+public abstract class StoreChunkReader implements IStoreChunkReader
+{
+  private IStoreAccessor accessor;
+
+  private CDORevision revision;
+
+  private EStructuralFeature feature;
+
+  private List<Chunk> chunks = new ArrayList<Chunk>(0);
+
+  public StoreChunkReader(IStoreAccessor accessor, CDORevision revision, EStructuralFeature feature)
+  {
+    this.accessor = accessor;
+    this.revision = revision;
+    this.feature = feature;
+  }
+
+  public IStoreAccessor getAccessor()
+  {
+    return accessor;
+  }
+
+  public CDORevision getRevision()
+  {
+    return revision;
+  }
+
+  public EStructuralFeature getFeature()
+  {
+    return feature;
+  }
+
+  public List<Chunk> getChunks()
+  {
+    return chunks;
+  }
+
+  public void addSimpleChunk(int index)
+  {
+    chunks.add(new Chunk(index));
+  }
+
+  public void addRangedChunk(int fromIndex, int toIndex)
+  {
+    chunks.add(new Chunk(fromIndex, toIndex - fromIndex));
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/SyncingUtil.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/SyncingUtil.java
new file mode 100644
index 0000000..a6eef70
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/SyncingUtil.java
@@ -0,0 +1,60 @@
+/**
+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.spi.server;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockArea;
+import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockAreaNotFoundException;
+
+import org.eclipse.net4j.util.CheckUtil;
+
+/**
+ * Static methods that may help with classes related to repository synchronization.
+ * 
+ * @author Eike Stepper
+ * @since 4.1
+ */
+public final class SyncingUtil
+{
+  private SyncingUtil()
+  {
+  }
+
+  public static InternalView openViewWithLockArea(InternalSession session, InternalLockManager lockManager,
+      CDOBranch viewedBranch, String lockAreaID)
+  {
+    LockArea lockArea;
+    InternalView view;
+
+    try
+    {
+      lockArea = lockManager.getLockArea(lockAreaID);
+
+      // If we get here, the lockArea already exists.
+      view = (InternalView)lockManager.openView(session, InternalSession.TEMP_VIEW_ID, true, lockAreaID);
+    }
+    catch (LockAreaNotFoundException e)
+    {
+      // If we get here, the lockArea does not yet exist, so we open
+      // a view without a lockArea first, then create a lockArea with the given ID,
+      // and associate it with the view.
+      view = session.openView(InternalSession.TEMP_VIEW_ID, viewedBranch.getHead());
+      lockArea = lockManager.createLockArea(view, lockAreaID);
+      view.setDurableLockingID(lockAreaID);
+    }
+
+    CheckUtil.checkNull(lockAreaID, "lockAreaID");
+    CheckUtil.checkNull(lockArea, "lockArea");
+    CheckUtil.checkState(lockAreaID.equals(lockArea.getDurableLockingID()), "lockAreaID has incorrect value");
+
+    return view;
+  }
+}
diff --git a/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/package-info.java b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/package-info.java
new file mode 100644
index 0000000..f320267
--- /dev/null
+++ b/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/package-info.java
@@ -0,0 +1,18 @@
+/*

+ * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others.

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ * 

+ * Contributors:

+ *    Eike Stepper - initial API and implementation

+ */

+

+/**

+ * Server service provider interfaces and useful base implementations.

+ * 

+ * @apiviz.exclude .*

+ */

+package org.eclipse.emf.cdo.spi.server;

+