pax_global_header 0000666 0000000 0000000 00000000064 12224530032 0014503 g ustar 00root root 0000000 0000000 52 comment=7d6f37ec87b01b9d1c2dabe5b4078a36f7c06e98
basex-7.7.2/ 0000775 0000000 0000000 00000000000 12224530032 0012622 5 ustar 00root root 0000000 0000000 basex-7.7.2/.gitignore 0000664 0000000 0000000 00000000147 12224530032 0014614 0 ustar 00root root 0000000 0000000 ## generic files to ignore
*~
*.lock
*.DS_Store
*.swp
*.out
org.maven.ide.eclipse.prefs
.idea/
*.class
basex-7.7.2/basex-api/ 0000775 0000000 0000000 00000000000 12224530032 0014473 5 ustar 00root root 0000000 0000000 basex-7.7.2/basex-api/.checkstyle 0000664 0000000 0000000 00000001236 12224530032 0016634 0 ustar 00root root 0000000 0000000
basex-7.7.2/basex-api/.classpath 0000664 0000000 0000000 00000001404 12224530032 0016455 0 ustar 00root root 0000000 0000000
basex-7.7.2/basex-api/.gitignore 0000664 0000000 0000000 00000000022 12224530032 0016455 0 ustar 00root root 0000000 0000000 /doc
/lib
/target
basex-7.7.2/basex-api/.project 0000664 0000000 0000000 00000001635 12224530032 0016147 0 ustar 00root root 0000000 0000000
basex-apiorg.eclipse.jdt.core.javabuildernet.sf.eclipsecs.core.CheckstyleBuilderorg.maven.ide.eclipse.maven2Builderorg.eclipse.m2e.core.maven2Builderorg.eclipse.m2e.core.maven2Natureorg.maven.ide.eclipse.maven2Natureorg.eclipse.jdt.core.javanaturenet.sf.eclipsecs.core.CheckstyleNature
basex-7.7.2/basex-api/.settings/ 0000775 0000000 0000000 00000000000 12224530032 0016411 5 ustar 00root root 0000000 0000000 basex-7.7.2/basex-api/.settings/checkstyle.xml 0000664 0000000 0000000 00000012116 12224530032 0021272 0 ustar 00root root 0000000 0000000
basex-7.7.2/basex-api/.settings/org.eclipse.core.resources.prefs 0000664 0000000 0000000 00000000271 12224530032 0024624 0 ustar 00root root 0000000 0000000 eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding//src/main/resources=UTF-8
encoding//src/test/java=UTF-8
encoding//src/test/resources=UTF-8
encoding/=UTF-8
basex-7.7.2/basex-api/.settings/org.eclipse.core.runtime.prefs 0000664 0000000 0000000 00000000121 12224530032 0024267 0 ustar 00root root 0000000 0000000 #Mon Feb 14 18:03:25 CET 2011
eclipse.preferences.version=1
line.separator=\n
basex-7.7.2/basex-api/.settings/org.eclipse.jdt.core.prefs 0000664 0000000 0000000 00000072670 12224530032 0023407 0 ustar 00root root 0000000 0000000 eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.6
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.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=ignore
org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=enabled
org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=enabled
org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
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=warning
org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning
org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning
org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled
org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled
org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private
org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning
org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning
org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning
org.eclipse.jdt.core.compiler.problem.missingJavadocComments=warning
org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=private
org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=all_standard_tags
org.eclipse.jdt.core.compiler.problem.missingJavadocTags=warning
org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=enabled
org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=enabled
org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=private
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore
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.nullAnnotationInferenceConflict=error
org.eclipse.jdt.core.compiler.problem.nullReference=warning
org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
org.eclipse.jdt.core.compiler.problem.parameterAssignment=warning
org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning
org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning
org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=enabled
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.unavoidableGenericTypeProblems=enabled
org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
org.eclipse.jdt.core.compiler.problem.unclosedCloseable=ignore
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=warning
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=disabled
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=disabled
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=warning
org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=disabled
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.6
org.eclipse.jdt.core.compiler.taskCaseSensitive=disabled
org.eclipse.jdt.core.compiler.taskPriorities=NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL
org.eclipse.jdt.core.compiler.taskTags=TODO,[CG],[AH],[LK],[CG],[MS],[DP],[LW],[JE],[DK],[MSG]
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=90
org.eclipse.jdt.core.formatter.alignment_for_enum_constants=16
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=0
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=0
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=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
org.eclipse.jdt.core.formatter.comment.clear_blank_lines=true
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=false
org.eclipse.jdt.core.formatter.comment.format_block_comments=true
org.eclipse.jdt.core.formatter.comment.format_comments=false
org.eclipse.jdt.core.formatter.comment.format_header=true
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=do not insert
org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert
org.eclipse.jdt.core.formatter.comment.line_length=96
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=true
org.eclipse.jdt.core.formatter.indentation.size=2
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
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_method=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=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_annotation_on_type=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=do not 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=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not 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=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=do not 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=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=do not 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=do not 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=do not 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=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=do not 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=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=do not 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=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.keep_else_statement_on_same_line=true
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=true
org.eclipse.jdt.core.formatter.lineSplit=96
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
basex-7.7.2/basex-api/.settings/org.eclipse.jdt.ui.prefs 0000664 0000000 0000000 00000005334 12224530032 0023065 0 ustar 00root root 0000000 0000000 #Sat Feb 04 16:59:42 CET 2012
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=false
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=true
cleanup.correct_indentation=false
cleanup.format_source_code=false
cleanup.format_source_code_changes_only=false
cleanup.make_local_variable_final=true
cleanup.make_parameters_final=true
cleanup.make_private_fields_final=true
cleanup.make_type_abstract_if_missing_method=false
cleanup.make_variable_declarations_final=true
cleanup.never_use_blocks=false
cleanup.never_use_parentheses_in_expressions=true
cleanup.organize_imports=false
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=true
cleanup.qualify_static_method_accesses_with_declaring_class=false
cleanup.remove_private_constructors=true
cleanup.remove_trailing_whitespaces=false
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=false
cleanup.use_blocks_only_for_return_and_throw=false
cleanup.use_parentheses_in_expressions=true
cleanup.use_this_for_non_static_field_access=false
cleanup.use_this_for_non_static_field_access_only_if_necessary=true
cleanup.use_this_for_non_static_method_access=false
cleanup.use_this_for_non_static_method_access_only_if_necessary=true
cleanup_profile=_BaseX
cleanup_settings_version=2
eclipse.preferences.version=1
formatter_profile=_BaseX Formatter Profile
formatter_settings_version=11
org.eclipse.jdt.ui.ignorelowercasenames=true
org.eclipse.jdt.ui.importorder=java;javax;org;com;
org.eclipse.jdt.ui.ondemandthreshold=1
org.eclipse.jdt.ui.staticondemandthreshold=1
basex-7.7.2/basex-api/.settings/org.eclipse.ltk.core.refactoring.prefs 0000664 0000000 0000000 00000000211 12224530032 0025700 0 ustar 00root root 0000000 0000000 #Fri Mar 19 00:48:33 CET 2010
eclipse.preferences.version=1
org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false
basex-7.7.2/basex-api/.settings/org.eclipse.m2e.core.prefs 0000664 0000000 0000000 00000000172 12224530032 0023275 0 ustar 00root root 0000000 0000000 #Wed Aug 03 00:22:23 CEST 2011
activeProfiles=
eclipse.preferences.version=1
resolveWorkspaceProjects=true
version=1
basex-7.7.2/basex-api/.settings/org.maven.ide.eclipse.prefs 0000664 0000000 0000000 00000000417 12224530032 0023533 0 ustar 00root root 0000000 0000000 #Fri Jan 29 18:36:39 CET 2010
activeProfiles=
eclipse.preferences.version=1
fullBuildGoals=process-test-resources
includeModules=false
resolveWorkspaceProjects=true
resourceFilterGoals=process-resources resources\:testResources
skipCompilerPlugin=true
version=1
basex-7.7.2/basex-api/basex-api.iml 0000664 0000000 0000000 00000007515 12224530032 0017057 0 ustar 00root root 0000000 0000000
basex-7.7.2/basex-api/etc/ 0000775 0000000 0000000 00000000000 12224530032 0015246 5 ustar 00root root 0000000 0000000 basex-7.7.2/basex-api/etc/basexhttp 0000775 0000000 0000000 00000001404 12224530032 0017175 0 ustar 00root root 0000000 0000000 #!/usr/bin/env bash
# Path to this script
FILE="${BASH_SOURCE[0]}"
while [ -h "$FILE" ] ; do
SRC="$(readlink "$FILE")"
FILE="$( cd -P "$(dirname "$FILE")" && \
cd -P "$(dirname "$SRC")" && pwd )/$(basename "$SRC")"
done
BX="$( cd -P "$(dirname "$FILE")/.." && pwd )"
BXCORE="$( cd -P "$BX/../basex" && pwd )"
# API, core, and library classes
CP="$BX/target/classes$(printf ":%s" "$BX/BaseX.jar" "$BX/lib/"*.jar "$BXCORE/target/classes" "$BXCORE/lib/"*.jar)"
# Options for virtual machine
VM=-Xmx512m
general_args=( )
vm_args=( )
while (( $# )) ; do
if [[ $1 = "-X" ]] ; then
vm_args+=( "$2" )
shift 2
else
general_args+=( "$1" )
shift
fi
done
# Run code
java -cp "$CP" $VM "${vm_args[@]}" org.basex.BaseXHTTP "${general_args[@]}"
basex-7.7.2/basex-api/etc/basexhttp.bat 0000664 0000000 0000000 00000000642 12224530032 0017742 0 ustar 00root root 0000000 0000000 @echo off
setLocal EnableDelayedExpansion
REM Path to this script
set PWD=%~dp0
REM Core and library classes
set CP=%PWD%/../target/classes
set LIB=%PWD%/../lib
for /R "%LIB%" %%a in (*.jar) do set CP=!CP!;%%a
set LIB=%PWD%/../../basex/lib
for /R "%LIB%" %%a in (*.jar) do set CP=!CP!;%%a
REM Options for virtual machine
set VM=-Xmx512m
REM Run code
java -cp "%CP%;." %VM% org.basex.BaseXHTTP %*
basex-7.7.2/basex-api/etc/basexhttpstop 0000775 0000000 0000000 00000001401 12224530032 0020100 0 ustar 00root root 0000000 0000000 #!/usr/bin/env bash
# Path to this script
FILE="${BASH_SOURCE[0]}"
while [ -h "$FILE" ] ; do
SRC="$(readlink "$FILE")"
FILE="$( cd -P "$(dirname "$FILE")" && \
cd -P "$(dirname "$SRC")" && pwd )/$(basename "$SRC")"
done
BX="$( cd -P "$(dirname "$FILE")/.." && pwd )"
BXCORE="$( cd -P "$BX/../basex" && pwd )"
# API, core, and library classes
CP="$BX/target/classes$(printf ":%s" "$BX/BaseX.jar" "$BX/lib/"*.jar "$BXCORE/target/classes" "$BXCORE/lib/"*.jar)"
# Options for virtual machine
VM=
general_args=( )
vm_args=( )
while (( $# )) ; do
if [[ $1 = "-X" ]] ; then
vm_args+=( "$2" )
shift 2
else
general_args+=( "$1" )
shift
fi
done
# Run code
java -cp "$CP" $VM "${vm_args[@]}" org.basex.BaseXHTTP "${general_args[@]}" stop
basex-7.7.2/basex-api/etc/basexhttpstop.bat 0000664 0000000 0000000 00000000641 12224530032 0020647 0 ustar 00root root 0000000 0000000 @echo off
setLocal EnableDelayedExpansion
REM Path to this script
set PWD=%~dp0
REM Core and library classes
set CP=%PWD%/../target/classes
set LIB=%PWD%/../lib
for /R "%LIB%" %%a in (*.jar) do set CP=!CP!;%%a
set LIB=%PWD%/../../basex/lib
for /R "%LIB%" %%a in (*.jar) do set CP=!CP!;%%a
REM Options for virtual machine
set VM=
REM Run code
java -cp "%CP%;." %VM% org.basex.BaseXHTTP %* stop
basex-7.7.2/basex-api/license.txt 0000664 0000000 0000000 00000003177 12224530032 0016666 0 ustar 00root root 0000000 0000000 ====================================================== BASEX LICENSE ===
Copyright (c) 2005-12 BaseX Team
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
========================================================================
basex-7.7.2/basex-api/pom.xml 0000664 0000000 0000000 00000007310 12224530032 0016011 0 ustar 00root root 0000000 0000000
4.0.0basex-apiorg.basexbasex-parent7.7.2..BaseX APIorg.basexbasex${project.version}net.xqjbasex-xqjorg.xmldbxmldb-apiorg.eclipse.jettyjetty-serverorg.eclipse.jettyjetty-servletorg.eclipse.jettyjetty-webappcom.ettremamilton-apicommons-fileuploadcommons-fileuploadorg.slf4jslf4j-nopjunitjunitcom.vividsolutionsjts${project.artifactId}-${project.version}org.apache.maven.pluginsmaven-compiler-pluginfalseorg.apache.maven.pluginsmaven-jar-pluginorg.apache.maven.pluginsmaven-surefire-pluginorg.apache.maven.pluginsmaven-source-pluginorg.mortbay.jettyjetty-maven-plugin${basedir}/src/main/webapp/WEB-INF/jetty.xmlorg.apache.maven.pluginsmaven-deploy-pluginorg.apache.maven.pluginsmaven-dependency-plugincompilexstream
basex-7.7.2/basex-api/src/ 0000775 0000000 0000000 00000000000 12224530032 0015262 5 ustar 00root root 0000000 0000000 basex-7.7.2/basex-api/src/main/ 0000775 0000000 0000000 00000000000 12224530032 0016206 5 ustar 00root root 0000000 0000000 basex-7.7.2/basex-api/src/main/as/ 0000775 0000000 0000000 00000000000 12224530032 0016611 5 ustar 00root root 0000000 0000000 basex-7.7.2/basex-api/src/main/as/Query.as 0000664 0000000 0000000 00000006161 12224530032 0020247 0 ustar 00root root 0000000 0000000 /**
* Language Binding for BaseX.
* Works with BaseX 7.0 and later
*
* Documentation: http://docs.basex.org/wiki/Clients
*
* (C) Manfred Knobloch, BSD License
* Institut für Wissensmedien IWM - Knowledge Media Research Center (KMRC)
**/
package basexapi
{
import flash.utils.ByteArray;
public class Query
{
public const NO_ID:int = 0;
public const CLOSED:int = -1;
public const PENDING_ID_REQUEST:int = 10;
public const ID_RECEIVED:int = 20;
public const PENDING_BIND_REQUEST:int = 30;
public const BIND_RESPONSE:int = 40;
public const EXECUTE_REQUEST:int = 50;
protected var _session:Session;
protected var _query:String;
protected var _name:String;
protected var _value:String;
[Bindable]
public var state:int=0;
public var id:String = "";
protected var socketBuffer:ByteArray;
public function Query(session:Session, query:String)
{
_session = session;
_query = query;
_name = "";
_value = "";
state = PENDING_ID_REQUEST;
socketBuffer = new ByteArray();
socketBuffer.writeByte(0);
socketBuffer.writeUTFBytes(_query);
socketBuffer.writeByte(0);
_session.sendBuffer(socketBuffer);
}
/**
* detect bind indicator 'declare' in query
* string
**/
public function needBind():Boolean{
var _lowerq:String = _query.toLowerCase();
if ( _lowerq.indexOf('declare') > -1){
return true;
}
return false;
}
public function setBindParams(name:String, value:String):void{
_name = name;
_value = value;
}
/**
* send 2 \0 bytes at end, otherwise bind will fail for
* the type parameter seems to be neccessary
* ('\x03', '0\x00$name\x00number\x00\x00')
**/
public function bind():void{
if (state > PENDING_ID_REQUEST){
state = PENDING_BIND_REQUEST;
socketBuffer = new ByteArray();
socketBuffer.writeByte(3);
socketBuffer.writeUTFBytes(id);
socketBuffer.writeByte(0);
socketBuffer.writeUTFBytes(_name);
socketBuffer.writeByte(0);
socketBuffer.writeUTFBytes(_value);
socketBuffer.writeByte(0); // termination for value
socketBuffer.writeByte(0); // termination for unused type
socketBuffer.position = 0;
_session.sendBuffer(socketBuffer);
}
}
public function sendQuery(code:int, arg:String):void{
socketBuffer = new ByteArray();
socketBuffer.writeByte(code);
socketBuffer.writeUTFBytes(this.id);
socketBuffer.writeByte(0);
_session.sendBuffer(socketBuffer);
}
public function execute():void{
sendQuery(0x05, id);
}
public function info():void{
exc(6, id);
}
public function options():void{
exc(7, id);
}
public function close():void{
exc(2, id);
}
public function exc(cmd:int, arg:String):void{
sendQuery(cmd, arg);
}
}
} basex-7.7.2/basex-api/src/main/as/Session.as 0000664 0000000 0000000 00000014022 12224530032 0020560 0 ustar 00root root 0000000 0000000 /**
* Language Binding for BaseX.
* Works with BaseX 7.0 and later
*
* Documentation: http://docs.basex.org/wiki/Clients
*
* (C) Manfred Knobloch, BSD License
* Institut für Wissensmedien IWM - Knowledge Media Research Center (KMRC)
**/
package basexapi
{
import com.adobe.crypto.MD5;
import flash.errors.*;
import flash.events.*;
import flash.net.Socket;
import flash.system.Security;
import flash.utils.ByteArray;
public class Session extends Object
{
public static const DISCONNECTED:int = 0;
public static const CONNECTING:int = 1;
public static const CONNECTED:int = 2;
public static const AUTHENTICATING:int = 3;
public static const AUTHENTICATED:int = 4;
public static const OPERATING:int = 5;
public static const RESULT:int = 6;
[Bindable]
public var response:String= "";
[Bindable]
protected var _socket:Socket;
[Bindable]
public var state:int = DISCONNECTED;
protected var _result:ByteArray;
protected var user:String;
protected var password:String;
protected var _query:Query;
public var socketBuffer:ByteArray;
public function Session(h:String=null, p:uint=0, u:String=null,
pass:String=null)
{
user = u;
password = pass;
_socket = new Socket();
_socket.addEventListener(Event.CLOSE, closeHandler);
_socket.addEventListener(Event.CONNECT, connectHandler);
_socket.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
_socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
_socket.addEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler);
state = CONNECTING;
_socket.connect(h,p);
socketBuffer = new ByteArray();
}
public function execute(arg:String):void{
socketBuffer = new ByteArray();
socketBuffer.writeUTFBytes(arg);
socketBuffer.writeByte(0);
sendBuffer(socketBuffer);
}
public function close():void{
_socket.close();
}
public function query(q:String):Query{
_query = new Query(this, q);
return _query;
}
public function sendCommand(code:int, arg:String, input:String):void{
socketBuffer = new ByteArray();
socketBuffer.writeByte(code);
socketBuffer.writeUTFBytes(arg);
socketBuffer.writeByte(0);
socketBuffer.writeUTFBytes(input);
socketBuffer.writeByte(0);
sendBuffer(socketBuffer);
}
public function sendBuffer(b:ByteArray):void{
response = "";
_socket.writeBytes(b);
_socket.flush();
}
protected function sendInput(code:int, arg:String):void{
var breakat:int = arg.indexOf(" ");
if (breakat == -1){
return;
}
var arg1:String = arg.substr(0,breakat);
var arg2:String = arg.substring(breakat);
sendCommand(code,arg1,arg2);
}
public function create(input:String):void{
sendInput(8,input);
}
public function add(input:String):void{
sendInput(9, input);
}
public function replace(input:String):void{
sendInput(12, input);
}
public function store(input:String):void{
sendInput(13,input);
}
public function authenticate():void{
var md5pw:String = MD5.hash(password);
var md5resp:String = MD5.hash(md5pw + response);
socketBuffer = new ByteArray();
socketBuffer.writeUTFBytes(user);
socketBuffer.writeByte(0);
socketBuffer.writeUTFBytes(md5resp);
socketBuffer.writeByte(0);
response = "";
_socket.writeBytes(socketBuffer);
_socket.flush();
state = AUTHENTICATING;
}
public function readIntoByteBuffer(buf:ByteArray):void{
_socket.readBytes(buf,0,_socket.bytesAvailable);
}
public function readstrings():String{
_result = new ByteArray();
var last:int = 0;
var current:int = 0;
var foundStrings:Vector. = new Vector.;
_socket.readBytes(_result,0,_socket.bytesAvailable);
//read to letter 0 or end of bytes
while (_result.bytesAvailable > 0 ) {
if(_result.readByte() == 0){
current = _result.position;
if (current > last){
_result.position = last;
foundStrings.push(_result.readUTFBytes(current-last));
last = current;
}
}
}
return foundStrings.join("");
}
// wrapper for public
public function readUTFBytes():String{
return _socket.readUTFBytes(_socket.bytesAvailable);
}
private function socketDataHandler(event:ProgressEvent):void {
if (state == AUTHENTICATING){
if( _socket.readByte() == 0){
state = AUTHENTICATED;
return;
}
}
response = readstrings();
if(_query && (_query.state == _query.PENDING_ID_REQUEST)){
_query.id = response;
_query.state = _query.ID_RECEIVED;
if (!_query.needBind()){
_query.execute();
return;
}
_query.bind();
return;
}
if(_query && (_query.state == _query.PENDING_BIND_REQUEST)){
_query.state = _query.BIND_RESPONSE
_query.execute();
return;
}
if (state < AUTHENTICATING){
authenticate();
state = AUTHENTICATING
}
}
// some string representations
public function get stateinfo():String{
var info:String = "";
switch (state) {
case DISCONNECTED:
info = "DISCONNECTED";
break;
case CONNECTING:
info = "CONNECTING";
break;
case CONNECTED:
info = "CONNECTED";
break;
case AUTHENTICATING:
info = "AUTHENTICATING";
break;
case AUTHENTICATED:
info = "AUTHENTICATED";
break;
case OPERATING:
info = "OPERATING";
break;
}
return info;
}
// handler functions
private function closeHandler(event:Event):void {
trace("closeHandler: " + event);
}
private function connectHandler(event:Event):void {
state = CONNECTED;
}
private function ioErrorHandler(event:IOErrorEvent):void {
trace("ioErrorHandler: " + event);
}
private function securityErrorHandler(event:SecurityErrorEvent):void {
trace("securityErrorHandler: " + event);
}
}
} basex-7.7.2/basex-api/src/main/c#/ 0000775 0000000 0000000 00000000000 12224530032 0016473 5 ustar 00root root 0000000 0000000 basex-7.7.2/basex-api/src/main/c#/AddExample.cs 0000664 0000000 0000000 00000002751 12224530032 0021033 0 ustar 00root root 0000000 0000000 /*
* This example shows how new documents can be added.
*
* Documentation: http://docs.basex.org/wiki/Clients
*
* (C) BaseX Team 2005-12, BSD License
*/
using System;
using System.Diagnostics;
using System.IO;
namespace BaseXClient
{
public class AddExample
{
public static void Main(string[] args)
{
try
{
// create session
Session session = new Session("localhost", 1984, "admin", "admin");
// create empty database
session.Execute("create db database");
Console.WriteLine(session.Info);
// define InputStream
MemoryStream ms = new MemoryStream(
System.Text.Encoding.UTF8.GetBytes("Hello World!"));
// add document
session.Add("world/world.xml", ms);
Console.WriteLine(session.Info);
// define InputStream
ms = new MemoryStream(
System.Text.Encoding.UTF8.GetBytes("Hello Universe!"));
// add document
session.Add("Universe.xml", ms);
Console.WriteLine(session.Info);
// run query on database
Console.WriteLine(session.Execute("xquery /"));
// drop database
session.Execute("drop db database");
// close session
session.Close();
}
catch (IOException e)
{
// print exception
Console.WriteLine(e.Message);
}
}
}
}
basex-7.7.2/basex-api/src/main/c#/BaseXClient.cs 0000664 0000000 0000000 00000016611 12224530032 0021170 0 ustar 00root root 0000000 0000000 /*
* Language Binding for BaseX.
* Works with BaseX 7.0 and later
*
* Documentation: http://docs.basex.org/wiki/Clients
*
* (C) BaseX Team 2005-12, BSD License
*/
using System;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.IO;
using System.Threading;
using System.Collections;
using System.Collections.Generic;
namespace BaseXClient
{
class Session
{
private byte[] cache = new byte[4096];
public NetworkStream stream;
private TcpClient socket;
private string info = "";
private string ehost;
private int bpos;
private int bsize;
private TcpClient esocket;
private NetworkStream estream;
private Dictionary en;
public Session(string host, int port, string username, string pw)
{
socket = new TcpClient(host, port);
stream = socket.GetStream();
ehost = host;
string ts = Receive();
Send(username);
Send(MD5(MD5(pw) + ts));
if (stream.ReadByte() != 0)
{
throw new IOException("Access denied.");
}
}
public void Execute(string com, Stream ms)
{
Send(com);
Init();
Receive(ms);
info = Receive();
if(!Ok())
{
throw new IOException(info);
}
}
public String Execute(string com)
{
MemoryStream ms = new MemoryStream();
Execute(com, ms);
return System.Text.Encoding.UTF8.GetString(ms.ToArray());
}
public Query Query(string q)
{
return new Query(this, q);
}
public void Create(string name, Stream s)
{
stream.WriteByte(8);
Send(name);
Send(s);
}
public void Add(string path, Stream s)
{
stream.WriteByte(9);
Send(path);
Send(s);
}
public void Replace(string path, Stream s)
{
stream.WriteByte(12);
Send(path);
Send(s);
}
public void Store(string path, Stream s)
{
stream.WriteByte(13);
Send(path);
Send(s);
}
/* Watches an event. */
public void Watch(string name, EventNotification notify)
{
stream.WriteByte(10);
if(esocket == null)
{
int eport = Convert.ToInt32(Receive());
en = new Dictionary();
esocket = new TcpClient(ehost, eport);
estream = esocket.GetStream();
string id = Receive();
byte[] msg = System.Text.Encoding.UTF8.GetBytes(id);
estream.Write(msg, 0, msg.Length);
estream.WriteByte(0);
estream.ReadByte();
new Thread(Listen).Start();
}
Send(name);
info = Receive();
if(!Ok())
{
throw new IOException(info);
}
en.Add(name, notify);
}
private void Listen()
{
while (true)
{
String name = readS();
String val = readS();
en[name].Update(val);
}
}
private string readS()
{
MemoryStream ms = new MemoryStream();
while (true)
{
int b = estream.ReadByte();
if (b == 0) break;
ms.WriteByte((byte) b);
}
return System.Text.Encoding.UTF8.GetString(ms.ToArray());
}
/* Unwatches an event. */
public void Unwatch(string name)
{
stream.WriteByte(11);
Send(name);
info = Receive();
if(!Ok())
{
throw new IOException(info);
}
en.Remove(name);
}
public string Info
{
get
{
return info;
}
}
public void Close()
{
Send("exit");
if (esocket != null)
{
esocket.Close();
}
socket.Close();
}
private void Init()
{
bpos = 0;
bsize = 0;
}
public byte Read()
{
if (bpos == bsize)
{
bsize = stream.Read(cache, 0, 4096);
bpos = 0;
}
return cache[bpos++];
}
private void Receive(Stream ms)
{
while (true)
{
byte b = Read();
if (b == 0) break;
ms.WriteByte(b);
}
}
public string Receive()
{
MemoryStream ms = new MemoryStream();
Receive(ms);
return System.Text.Encoding.UTF8.GetString(ms.ToArray());
}
public void Send(string message)
{
byte[] msg = System.Text.Encoding.UTF8.GetBytes(message);
stream.Write(msg, 0, msg.Length);
stream.WriteByte(0);
}
private void Send(Stream s)
{
while (true)
{
int t = s.ReadByte();
if (t == -1) break;
if (t == 0x00 || t == 0xFF) stream.WriteByte(Convert.ToByte(0xFF));
stream.WriteByte(Convert.ToByte(t));
}
stream.WriteByte(0);
info = Receive();
if(!Ok())
{
throw new IOException(info);
}
}
public bool Ok()
{
return Read() == 0;
}
private string MD5(string input)
{
MD5CryptoServiceProvider MD5 = new MD5CryptoServiceProvider();
byte[] hash = MD5.ComputeHash(Encoding.UTF8.GetBytes(input));
StringBuilder sb = new StringBuilder();
foreach (byte h in hash)
{
sb.Append(h.ToString("x2"));
}
return sb.ToString();
}
}
class Query
{
private Session session;
private string id;
private ArrayList cache;
private int pos;
public Query(Session s, string query)
{
session = s;
id = Exec(0, query);
}
public void Bind(string name, string value)
{
Bind(name, value, "");
}
public void Bind(string name, string value, string type)
{
cache = null;
Exec(3, id + '\0' + name + '\0' + value + '\0' + type);
}
public void Context(string value)
{
Context(value, "");
}
public void Context(string value, string type)
{
cache = null;
Exec(14, id + '\0' + value + '\0' + type);
}
public bool More()
{
if(cache == null)
{
session.stream.WriteByte(4);
session.Send(id);
cache = new ArrayList();
while (session.Read() > 0)
{
cache.Add(session.Receive());
}
if(!session.Ok())
{
throw new IOException(session.Receive());
}
pos = 0;
}
if(pos < cache.Count) return true;
cache = null;
return false;
}
public string Next()
{
if(More())
{
return cache[pos++] as string;
}
else
{
return null;
}
}
public string Execute()
{
return Exec(5, id);
}
public string Info()
{
return Exec(6, id);
}
public string Options()
{
return Exec(7, id);
}
public void Close()
{
Exec(2, id);
}
private string Exec(byte cmd, string arg)
{
session.stream.WriteByte(cmd);
session.Send(arg);
string s = session.Receive();
bool ok = session.Ok();
if(!ok)
{
throw new IOException(session.Receive());
}
return s;
}
}
interface EventNotification
{
void Update(string data);
}
} basex-7.7.2/basex-api/src/main/c#/CreateExample.cs 0000664 0000000 0000000 00000002113 12224530032 0021536 0 ustar 00root root 0000000 0000000 /*
* This example shows how new databases can be created.
*
* Documentation: http://docs.basex.org/wiki/Clients
*
* (C) BaseX Team 2005-12, BSD License
*/
using System;
using System.Diagnostics;
using System.IO;
namespace BaseXClient
{
public class CreateExample
{
public static void Main(string[] args)
{
try
{
// create session
Session session = new Session("localhost", 1984, "admin", "admin");
// define InputStream
MemoryStream ms = new MemoryStream(
System.Text.Encoding.UTF8.GetBytes("Hello World!"));
// create database
session.Create("database", ms);
Console.WriteLine(session.Info);
// run query on database
Console.WriteLine(session.Execute("xquery /"));
// drop database
session.Execute("drop db database");
// close session
session.Close();
}
catch (IOException e)
{
// print exception
Console.WriteLine(e.Message);
}
}
}
}
basex-7.7.2/basex-api/src/main/c#/EventExample.cs 0000664 0000000 0000000 00000002405 12224530032 0021420 0 ustar 00root root 0000000 0000000 /*
* This example shows how to use the event feature.
*
* Documentation: http://docs.basex.org/wiki/Clients
*
* (C) BaseX Team 2005-12, BSD License
*/
using System;
using System.Diagnostics;
using System.IO;
namespace BaseXClient
{
public class EventExample
{
public static void Main(string[] args)
{
try
{
// create session
Session session1 = new Session("localhost", 1984, "admin", "admin");
Session session2 = new Session("localhost", 1984, "admin", "admin");
session1.Execute("create event messenger");
session2.Watch("messenger", new Notification());
session2.Query("for $i in 1 to 1000000 where $i = 0 return $i").Execute();
session1.Query("db:event('messenger', 'Hello World!')").Execute();
session2.Unwatch("messenger");
session1.Execute("drop event messenger");
// close session
session1.Close();
session2.Close();
}
catch (IOException e)
{
// print exception
Console.WriteLine(e.Message);
}
}
}
class Notification : EventNotification
{
public void Update (string data)
{
Console.WriteLine("Message received: " + data);
}
}
} basex-7.7.2/basex-api/src/main/c#/Example.cs 0000664 0000000 0000000 00000002244 12224530032 0020417 0 ustar 00root root 0000000 0000000 /*
* This example shows how database commands can be executed.
*
* Documentation: http://docs.basex.org/wiki/Clients
*
* (C) BaseX Team 2005-12, BSD License
*/
using System;
using System.Diagnostics;
using System.IO;
namespace BaseXClient
{
public class Example
{
public static void Main(string[] args)
{
try
{
// initialize timer
Stopwatch watch = new Stopwatch();
watch.Start();
// create session
Session session = new Session("localhost", 1984, "admin", "admin");
// version 1: perform command and print returned string
Console.WriteLine(session.Execute("info"));
// version 2 (faster): perform command and pass on result to output stream
Stream stream = Console.OpenStandardOutput();
session.Execute("xquery 1 to 10", stream);
// close session
session.Close();
// print time needed
Console.WriteLine("\n" + watch.ElapsedMilliseconds + " ms.");
}
catch (IOException e)
{
// print exception
Console.WriteLine(e.Message);
}
}
}
}
basex-7.7.2/basex-api/src/main/c#/QueryBindExample.cs 0000664 0000000 0000000 00000002365 12224530032 0022246 0 ustar 00root root 0000000 0000000 /*
* This example shows how external variables can be bound to XQuery expressions.
*
* Documentation: http://docs.basex.org/wiki/Clients
*
* (C) BaseX Team 2005-12, BSD License
*/
using System;
using System.Diagnostics;
using System.IO;
namespace BaseXClient
{
public class QueryIteratorExample
{
public static void Main(string[] args)
{
try
{
// create session
Session session = new Session("localhost", 1984, "admin", "admin");
try
{
// create query instance
string input = "declare variable $name external;" +
"for $i in 1 to 10 return element { $name } { $i }";
Query query = session.Query(input);
// bind variable
query.Bind("$name", "number");
// print result
Console.WriteLine(query.Execute());
// close query
query.Close();
}
catch (IOException e)
{
// print exception
Console.WriteLine(e.Message);
}
// close session
session.Close();
}
catch (IOException e)
{
// print exception
Console.WriteLine(e.Message);
}
}
}
}
basex-7.7.2/basex-api/src/main/c#/QueryExample.cs 0000664 0000000 0000000 00000002407 12224530032 0021446 0 ustar 00root root 0000000 0000000 /*
* This example shows how queries can be executed in an iterative manner.
* Iterative evaluation will be slower, as more server requests are performed.
*
* Documentation: http://docs.basex.org/wiki/Clients
*
* (C) BaseX Team 2005-12, BSD License
*/
using System;
using System.Diagnostics;
using System.IO;
namespace BaseXClient
{
public class QueryIteratorExample
{
public static void Main(string[] args)
{
try
{
// create session
Session session = new Session("localhost", 1984, "admin", "admin");
try
{
// create query instance
string input = "for $i in 1 to 10 return Text { $i }";
Query query = session.Query(input);
// loop through all results
while (query.More())
{
Console.WriteLine(query.Next());
}
// close query
query.Close();
}
catch (IOException e)
{
// print exception
Console.WriteLine(e.Message);
}
// close session
session.Close();
}
catch (IOException e)
{
// print exception
Console.WriteLine(e.Message);
}
}
}
}
basex-7.7.2/basex-api/src/main/c/ 0000775 0000000 0000000 00000000000 12224530032 0016430 5 ustar 00root root 0000000 0000000 basex-7.7.2/basex-api/src/main/c/GNUmakefile 0000664 0000000 0000000 00000002322 12224530032 0020501 0 ustar 00root root 0000000 0000000 .PHONY: all lib clean clean-depend clean-all
include config.mk
LIBNAME= basexdbc
DBCLIB= lib$(LIBNAME).$(LIBSFX)
VERSION= 0.1
FDEBUG=
CC?= cc
CFLAGS+= -DBUILD="\"$(VERSION)\"" -fPIC
LDFLAGS+= -fPIC
LIBS+=
ifdef FDEBUG
CFLAGS+= -g -ggdb -DDEBUG
CFLAGS+= -Wno-long-long -Wall -W -Wnested-externs -Wformat=2
CFLAGS+= -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations
CFLAGS+= -Wwrite-strings -Wshadow -Wpointer-arith -Wsign-compare
CFLAGS+= -Wundef -Wbad-function-cast -Winline -Wcast-align
endif
SRCS= $(shell echo *.c)
OBJS= $(patsubst %.c,%.o,$(SRCS))
all: lib example
lib: $(DBCLIB)
example:
$(CC) -L. -l$(LIBNAME) example.c -o $@
$(DBCLIB): md5.o basexdbc.o readstring.o
$(CC) $(LIBS) $(LDFLAGS) -shared -o $@ $+
depend: $(SRCS)
$(CC) $(CFLAGS) -MM $(SRCS) >depend
install: lib
install -d -m555 /usr/lib/basex
install -d -m555 /usr/include/basex
install -m555 $(DBCLIB) /usr/lib/basex/
install -m444 basexdbc.h /usr/include/basex/
uninstall:
rm -rf /usr/lib/basex/
rm -rf /usr/include/basex/
clean:
rm -f $(DBCLIB)
rm -f ${OBJS}
rm -f example
clean-config:
rm -f config.mk
clean-depend:
rm -f depend
clean-all: clean clean-config clean-depend uninstall
include depend
basex-7.7.2/basex-api/src/main/c/README 0000664 0000000 0000000 00000001361 12224530032 0017311 0 ustar 00root root 0000000 0000000 BASEX DATABASE CLIENT FOR C ====================================================
Connect to running BaseX database server (basex.org) from C code.
Compile dependencies:
openssl
debian: apt-get install libssl-dev
Build (tested on Debian GNU/Linux unstable only):
$ make [all|lib|example]
# make install
Inspect and test example:
$ less example.c
$ ./example (or, if lib is not installed, $ LD_LIBRARY_PATH=. ./example)
Cleanup:
$ make clean
# make clean-all (removes 'make install'ed files as well)
License:
Copyright (c) 2005-12, Alexander Holupirek , BSD license
Bug reports:
https://github.com/holu/basexdbc/issues
Have fun.
Alex
================================================================================
basex-7.7.2/basex-api/src/main/c/basexdbc.c 0000664 0000000 0000000 00000022657 12224530032 0020363 0 ustar 00root root 0000000 0000000 /**
* basexdbc.c : communicate with BaseX database server
*
* Copyright (c) 2005-12, Alexander Holupirek , BSD license
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "basexdbc.h"
#include "md5.h"
#include "readstring.h"
static int send_db(int sfd, const char *buf, size_t buf_len);
static int basex_status(int sfd);
/**
* Connect to host on port using stream sockets.
*
* @param host string representing host to connect to
* @param port string representing port on host to connect to
* @return socket file descriptor or -1 in case of failure
*/
int
basex_connect(const char *host, const char *port)
{
struct addrinfo hints;
struct addrinfo *result = NULL, *rp;
int sfd, rc;
if (host == NULL || port == NULL) {
#if DEBUG
warnx("Missing hostname '%s' / port '%s'.", host, port);
#endif
return -1;
}
/* Obtain address(es) matching host/port */
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC; /* Allows IPv4 or IPv6 */
hints.ai_socktype = SOCK_STREAM; /* TCP socket */
hints.ai_flags = AI_NUMERICSERV;
rc = getaddrinfo(host, port, &hints, &result);
if (rc != 0) {
#if DEBUG
warnx("getaddrinfo: %s", gai_strerror(rc));
#endif
return -1;
}
/* getaddrinfo() returns a list of address structures.
* Try each address until we successfully connect(2).
* If socket(2) (or connect(2)) fails, we (close the
* socket and) try the next address. */
for (rp = result; rp != NULL; rp = rp->ai_next) {
sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (sfd == -1)
continue; /* On error, try next address */
if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1)
break; /* Success */
close(sfd); /* Connect failed: close socket, try next address */
}
if (rp == NULL) { /* No address succeeded */
warnx("Can not connect to BaseX server.");
warnx("Hostname '%s', port %s.", host, port);
return -1;
}
freeaddrinfo(result); /* No longer needed */
return sfd; /* This file descriptor is ready for I/O. */
}
/**
* Authenticate against BaseX server connected on sfd using user and passwd.
*
* Authentication as defined by BaseX transfer protocol (BaseX 7.0 ff.):
* https://github.com/BaseXdb/basex-api/blob/master/etc/readme.txt
* {...} = string; \n = single byte
*
* 1. Client connects to server socket (basex_connect)
* 2. Server sends timestamp: {timestamp} \0
* 3. Client sends username and hash:
* {username} \0 {md5(md5(password) + timestamp)} \0
* 4. Server sends \0 (success) or \1 (error)
*
* @param sfd socket file descriptor successfully connected to BaseX server
* @param user string with database username
* @param passwd string with password for database username
* @return 0 in case of success, -1 in case of failure
*/
int
basex_authenticate(int sfd, const char *user, const char *passwd)
{
char ts[BUFSIZ]; /* timestamp returned by basex. */
char *md5_pwd; /* md5'ed passwd */
int ts_len, rc, i;
/* Right after the first connect BaseX returns a nul-terminated
* timestamp string. */
memset(ts, 0, BUFSIZ);
rc = read(sfd, &ts, BUFSIZ);
if (rc == -1) {
warnx("Reading timestamp failed.");
return -1;
}
ts_len = strlen(ts);
#if DEBUG
warnx("timestamp : %s (%d)", ts, strlen(ts));
#endif
/* BaseX Server expects an authentification sequence:
* {username}\0{md5(md5(password) + timestamp)}\0 */
/* Send {username}\0 */
int user_len = strlen(user) + 1;
rc = write(sfd, user, user_len);
if (rc == -1 || rc != user_len) {
warnx("Sending username failed. %d != %d", rc, user_len);
return -1;
}
/* Compute md5 for passwd. */
md5_pwd = md5(passwd);
if (md5_pwd == NULL) {
warnx("md5 computation for password failed.");
return -1;
}
int md5_pwd_len = strlen(md5_pwd);
#if DEBUG
warnx("md5(pwd) : %s (%d)", md5_pwd, md5_pwd_len);
#endif
/* Concat md5'ed passwd string and timestamp string. */
int pwdts_len = md5_pwd_len + ts_len + 1;
char pwdts[pwdts_len];
memset(pwdts, 0, sizeof(pwdts));
for (i = 0; i < md5_pwd_len; i++)
pwdts[i] = md5_pwd[i];
int j = md5_pwd_len;
for (i = 0; i < ts_len; i++,j++)
pwdts[j] = ts[i];
pwdts[pwdts_len - 1] = '\0';
#if DEBUG
warnx("md5(pwd)+ts : %s (%d)", pwdts, strlen(pwdts));
#endif
/* Compute md5 for md5'ed password + timestamp */
char *md5_pwdts = md5(pwdts);
if (md5_pwdts == NULL) {
warnx("md5 computation for password + timestamp failed.");
return -1;
}
int md5_pwdts_len = strlen(md5_pwdts);
#if DEBUG
warnx("md5(md5(pwd)+ts): %s (%d)", md5_pwdts, md5_pwdts_len);
#endif
/* Send md5'ed(md5'ed password + timestamp) to basex. */
rc = send_db(sfd, md5_pwdts, md5_pwdts_len + 1); // also send '\0'
if (rc == -1) {
warnx("Sending credentials failed.");
return -1;
}
free(md5_pwd);
free(md5_pwdts);
/* Retrieve authentification status. */
rc = basex_status(sfd);
if (rc == -1) {
warnx("Reading authentification status failed.");
return -1;
}
if (rc != 0) {
warnx("Authentification failed");
return -1;
}
#if DEBUG
warnx("Authentification succeded.");
#endif
return 0;
}
/**
* Read status single byte from socket.
*/
int
basex_status(int sfd)
{
char c;
int b = read(sfd, &c, 1);
if (b == -1) {
warnx("Can not retrieve status code.");
return -1;
}
return c;
}
/**
* Executes a command and returns a result string and an info/error string.
*
* A database command is sent to BaseX server connected on sfd.
* The result is a \0 terminated, dynamically allocated string, which is placed
* at the given result address or NULL. The same holds for the processing
* information stored at info.
*
* In either case it is the responsibility of the caller to free(3) those
* strings.
*
* The returned int is 0 if the command could be processed successfully, in that
* case the result contains the result string of the command and info holds
* the processing information.
* If a value >0 is returned, the command could not be processed successfully,
* result contains NULL and info contains the database error message.
* If -1 is interned, an error occurred, result and info are set to NULL.
*
* int | result* | info* |
* -----+---------+-------|
* -1 | NULL | NULL |
* 0 | result | info |
* >0 | NULL | error |
*
* * strings shall be free(3)'ed by caller
*
* BaseX C/S protocol:
*
* client sends: {command} \0
* server sends: {result} \0 {info} \0 \0
* or \0 {error} \0 \1
*
* @param sfd socket file descriptor connected to BaseX server
* @param command to be processed by BaseX server
* @param result address at which result from BaseX server is placed
* @param info address at which info/error message from BaseX server is placed
* @return int 0 for success (result and info contain strings sent from BaseX)
* -1 in case of failure (result and info are set to NULL), >0 an error occurred
* while processing the command (result contains NULL, info contains error
* message)
*/
int
basex_execute(int sfd, const char *command, char **result, char **info)
{
int rc;
/* Send {command}\0 to server. */
rc = send_db(sfd, command, strlen(command) + 1);
if (rc == -1) {
warnx("Can not send command '%s' to server.", command);
goto err;
}
/* --- Receive from server: {result} \0 {info} \0 \0
* \0 {error} \0 \1 */
/* Receive {result} \0 */
rc = readstring(sfd, result);
if (rc == -1) {
warnx("Can not retrieve result for command '%s' from server.", command);
goto err;
}
#if DEBUG
warnx("[execute] result: '%s'\n", *result);
#endif
/* Receive {info/error} \0 .*/
rc = readstring(sfd, info);
if (rc == -1) {
warnx("Can not retrieve info for command '%s' from server.", *info);
goto err;
}
#if DEBUG
warnx("[execute] info/error: '%s'\n", *info);
#endif
/* Receive terminating \0 for success or \1 for error .*/
rc = basex_status(sfd);
#if DEBUG
warnx("[execute] status: '%d'\n", rc);
#endif
if (rc == -1) {
warnx("Can not retrieve status.");
goto err;
}
if (rc == 1) {
warnx("BaseX error message : %s", *info);
free(*result);
*result = NULL;
}
assert(rc == 0 || rc == 1);
return rc;
err:
*result = NULL;
*info = NULL;
return -1;
}
/**
* Quits database session and closes stream connection to database server.
*
* @param socket file descriptor for database session.
*/
void
basex_close(int sfd)
{
/* Send {exit}\0 to server. */
int rc = send_db(sfd, "exit", 4 + 1);
if (rc != 0)
warnx("Can not send 'exit' command to server.");
/* Close socket. */
rc = shutdown(sfd, SHUT_RDWR);
if (rc == -1)
warn("Can not properly shutdown socket.");
}
/**
* Writes buffer buf of buf_len to socket sfd.
*
* @param socket file descriptor for database session.
* @param buf to be sent to server
* @param buf_len # of bytes in buf
* @return 0 if all data has successfully been written to server,
* -1 in case of failure.
*/
static int
send_db(int sfd, const char *buf, size_t buf_len)
{
ssize_t ret;
while (buf_len != 0 && (ret = write(sfd, buf, buf_len)) != 0) {
if (ret == -1) {
if (errno == EINTR)
continue;
warn("Can not write to server");
return -1;
}
#if DEBUG
int i;
warnx("write: \n");
for (i = 0; i < ret; i++)
warnx("[write] %3d : 0x%08x %4d %c", i, buf[i], buf[i], buf[i]);
#endif /* DEBUG */
buf_len -= ret;
buf += ret;
}
return 0;
}
basex-7.7.2/basex-api/src/main/c/basexdbc.h 0000664 0000000 0000000 00000001757 12224530032 0020366 0 ustar 00root root 0000000 0000000 /**
* basexdbc.h : communicate with BaseX database server
*
* Copyright (c) 2005-12, Alexander Holupirek , BSD license
*/
/* Connect to BaseX server and open session. Returns socket file descriptor. */
int basex_connect(const char *host, const char *port);
/* Authenticate for this session (passing socket desc, db user, and passwd). */
int basex_authenticate(int sfd, const char *user, const char *passwd);
/* Send database command to server.
* Expect result and info to be filled (must be free(3)'ed afterwards).
*
* int | result | info |
* -----+--------+-------|
* -1 | NULL | NULL | general error (i/o and the like)
* 0 | result | info | database command has been processed successfully
* >0 | NULL | error | database command processing failed
*
* BaseX commands: http://docs.basex.org/wiki/Commands
*/
int basex_execute(int sfd, const char *command, char **result, char **info);
/* Close session with descriptor sfd. */
void basex_close(int sfd);
basex-7.7.2/basex-api/src/main/c/changelog 0000664 0000000 0000000 00000000156 12224530032 0020304 0 ustar 00root root 0000000 0000000 basexdbc (0.1)
* Initial release.
-- Alexander Holupirek Sat May 14 16:59:07 CEST 2011
basex-7.7.2/basex-api/src/main/c/config.h 0000664 0000000 0000000 00000000015 12224530032 0020042 0 ustar 00root root 0000000 0000000 /* Darwin */
basex-7.7.2/basex-api/src/main/c/configure 0000664 0000000 0000000 00000003035 12224530032 0020335 0 ustar 00root root 0000000 0000000 #!/bin/sh
#
# Copyright (c) 2011 Alexander Holupirek
# Copyright (c) 2009 Nicholas Marriott
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
# OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
DBC_PLATFORM=${DBC_PLATFORM:-`uname -s`}
CONFIG_H=config.h
rm -f $CONFIG_H
echo "/* $DBC_PLATFORM */" >$CONFIG_H
CONFIG_MK=config.mk
rm -f $CONFIG_MK
echo "# $DBC_PLATFORM" >$CONFIG_MK
case $DBC_PLATFORM in
# ------------------------------------------------------------------------------
Linux)
cat <>$CONFIG_MK
LIBSFX=so
LIBS+= -lssl
EOF
;;
# ------------------------------------------------------------------------------
Darwin)
cat <>$CONFIG_MK
LIBSFX=dylib
LIBS+= -lcrypto
EOF
;;
# ------------------------------------------------------------------------------
*)
echo Unable to configure for $DBC_PLATFORM
exit 1
esac
echo Configured for $DBC_PLATFORM
exit 0
basex-7.7.2/basex-api/src/main/c/example.c 0000664 0000000 0000000 00000003105 12224530032 0020226 0 ustar 00root root 0000000 0000000 /* Copyright (c) 2005-12, Alexander Holupirek , BSD license */
#include
#include
#include
#include
#include "basexdbc.h"
/* once libbasexdbc.so is installed in /usr/include/basex/ use:
#include "basex/basexdbc.h"
*/
#define DBHOST "localhost"
#define DBPORT "1984"
#define DBUSER "admin"
#define DBPASSWD "admin"
/*
* Example to demonstrate communication with running BaseX database server.
*
* $ cc -L. -lbasexdbc example.c -o example
*/
int
main(void)
{
int sfd, rc;
/* Connect to server and receive socket descriptor for this session. */
sfd = basex_connect(DBHOST, DBPORT);
if (sfd == -1) {
warnx("Can not connect to BaseX server.");
return 0;
}
/* We are connected, let's authenticate for this session. */
rc = basex_authenticate(sfd, DBUSER, DBPASSWD);
if (rc == -1) {
warnx("Access to DB denied.");
goto out;
}
/* Send command in default mode and receive the result string. */
const char *command = "xquery 1 + 1";
char *result;
char *info;
rc = basex_execute(sfd, command, &result, &info);
if (rc == -1) { // general (i/o or the like) error
warnx("An error occured during execution of '%s'.", command);
goto free_and_out;
}
if (rc == 1) { // database error while processing command
warnx("Processing of '%s' failed.", command);
}
/* print command, result and info/error */
printf("command: '%s'\n", command);
printf("result : '%s'\n", result);
printf("%s : '%s'\n", (rc == 1) ? "error" : "info", info);
free_and_out:
free(result);
free(info);
out:
basex_close(sfd);
return 0;
}
basex-7.7.2/basex-api/src/main/c/md5.c 0000664 0000000 0000000 00000004063 12224530032 0017264 0 ustar 00root root 0000000 0000000 /* Copyright (c) 2005-12, Alexander Holupirek , BSD license */
#include
#include
#include
#include
#include "md5.h"
/**
* Print ascii hex representation of md5 value to newly allocated string.
*/
static int
md5toa(unsigned char *md_value, unsigned int md_len, char **md5_string)
{
unsigned int i, j;
int rc;
int hex_len = 3; // hex length to be printed xx\0
unsigned int length = 32; // length of md5 ascii hex representation
*md5_string = calloc(length + 1, sizeof(char));
if (*md5_string == NULL) {
warnx("Can not allocate memory for md5 ascii hex string.");
return -1;
}
for (i = 0, j = 0; i < md_len && j < length; i++, j += 2) {
rc = snprintf((*md5_string) + j, hex_len, "%02x", md_value[i]);
if (!(rc > -1 && rc < hex_len)) {
warnx("Construction of md5 ascii hex string failed.");
return -1;
}
}
(*md5_string)[length] = '\0'; // is already \0, but we are defensive
return 0;
}
/**
* Consult EVP_DigestInit(3SSL) for details.
*/
static char *
md5_digest(int n, ...)
{
EVP_MD_CTX mdctx;
const EVP_MD *md;
unsigned char md_value[EVP_MAX_MD_SIZE];
unsigned int md_len = 0;
int i, rc;
char *string;
char *md5_result = NULL;
OpenSSL_add_all_digests();
md = EVP_md5();
if(!md)
err(1, "Unknown message digest");
EVP_MD_CTX_init(&mdctx);
EVP_DigestInit_ex(&mdctx, md, NULL);
va_list argPtr;
va_start(argPtr, n);
for (i = 0; i < n; i++) {
string = va_arg(argPtr, char *);
EVP_DigestUpdate(&mdctx, string, strlen(string));
}
va_end(argPtr);
EVP_DigestFinal_ex(&mdctx, md_value, &md_len);
EVP_MD_CTX_cleanup(&mdctx);
EVP_cleanup();
rc = md5toa(md_value, md_len, &md5_result);
if (rc == -1)
err(1, "md5 digest failure.");
return md5_result;
}
/**
* Compute 128bit MD5 digest for string.
*
* @param string from which digest shall be computed
* @return Allocated C string containing the hex result representation is
* returned. It should be passed to free(3). On failure NULL is returned.
*/
char *
md5(const char *string)
{
return md5_digest(1, string);
}
basex-7.7.2/basex-api/src/main/c/md5.h 0000664 0000000 0000000 00000000557 12224530032 0017275 0 ustar 00root root 0000000 0000000 /* Copyright (c) 2005-12, Alexander Holupirek , BSD license */
/**
* Compute 128bit MD5 digest for string.
*
* @param string from which digest shall be computed
* @return Allocated C string containing the hex result representation is
* returned. It should be passed to free(3). On failure NULL is returned.
*/
char *md5(const char *string);
basex-7.7.2/basex-api/src/main/c/readstring.c 0000664 0000000 0000000 00000004262 12224530032 0020742 0 ustar 00root root 0000000 0000000 /* Copyright (c) 2005-12, Alexander Holupirek , BSD license */
#include
#include
#include
#include
#include
#include
#include
#include
#include "readstring.h"
static size_t READSTRING_MAX = 1024 * 1024 * 10; // 10MB
/**
* Reads string from file descriptor into dynamically allocated string.
*
* A variable length of characters is read from fd until a \0 byte
* is detected or a predefined maximum READSTRING_MAX is reached.
* The read bytes are stored into a dynamically allocated buffer str.
* It is the responsibility of the caller to free(3) str.
*
* @param fd file descriptor to read from
* @param str address of the newly allocated c string
* @return number of characters read or -1 in case of failure
* in case of an error str is set to NULL
*/
ssize_t
readstring(int fd, char **str)
{
char b;
int rb; // # of read byte (-1, 0, or 1)
size_t chars = 0; // # of stored chars in str
size_t size = 32; // start capacity of alloc'ed string
// allocate default capacity
*str = calloc(size, sizeof(char));
if (str == NULL) {
warn("malloc failed.");
return -1;
}
// read until \0 is detected or predefined maximum is reached
while(1) {
if (!(chars < size - 1)) { // reallocate
if (size && 2 > SIZE_MAX / size) {
errno = ENOMEM;
warn("overflow");
goto err;
}
size_t newsize = size * 2;
if (newsize < READSTRING_MAX) {
char *newstr;
if ((newstr = realloc(*str, newsize)) == NULL) {
warn("reallocation failed.");
goto err;
}
*str = newstr;
size = newsize;
} else {
errno = ENOBUFS;
warn("variable string exceeds maximum of %d"
, READSTRING_MAX);
goto err;
}
}
rb = read(fd, &b, 1);
if (rb == -1) {
if (rb == EINTR) // Interrupted, try again
continue;
else {
warn("Can not read");
goto err;
}
}
if (rb == 0) { // EOF
warnx("Hmm, we expected a \\0 before EOF.");
goto err;
}
// store another read char
*((*str) + chars) = b;
chars++;
if (b == '\0') { // We are done.
break;
}
}
return chars;
err:
free(*str);
*str = NULL;
return -1;
}
basex-7.7.2/basex-api/src/main/c/readstring.h 0000664 0000000 0000000 00000000173 12224530032 0020744 0 ustar 00root root 0000000 0000000 /* Copyright (c) 2005-12, Alexander Holupirek , BSD license */
ssize_t readstring(int fd, char **str);
basex-7.7.2/basex-api/src/main/haskell/ 0000775 0000000 0000000 00000000000 12224530032 0017631 5 ustar 00root root 0000000 0000000 basex-7.7.2/basex-api/src/main/haskell/BaseXClient.hs 0000664 0000000 0000000 00000005516 12224530032 0022335 0 ustar 00root root 0000000 0000000 -------------------------------------------------------------------------------
-- |
-- Module : BaseXClient
-- Copyright : (C) BaseX Team 2005-12
-- License : BSD
--
-- Maintainer : leo@woerteler.de
-- Stability : experimental
-- Portability : portable
--
-- Haskell client for BaseX.
-- Works with BaseX 6.1
--
-- It requires the PureMD5 package fom Hackage: 'cabal install PureMD5'.
--
-------------------------------------------------------------------------------
--
-- Example:
--
-- module Example where
-- import BaseXClient
-- import Network ( withSocketsDo )
-- main :: IO ()
-- main = withSocketsDo $ do
-- (Just session) <- connect "localhost" 1984 "admin" "admin"
-- execute session "xquery 1 to 10" >>= putStrLn . either id content
-- close session
--
-------------------------------------------------------------------------------
module BaseXClient ( connect, execute, close, Result(..) ) where
import Network ( withSocketsDo, PortID(..), PortNumber(..), connectTo )
import Control.Applicative ( (<$>) )
import System.IO ( Handle, hGetChar, hPutChar, hPutStr, hClose, BufferMode(..),
hSetBuffering, hFlush)
import qualified Data.Digest.Pure.MD5 as MD5 ( md5 )
import Data.ByteString.Lazy.UTF8 ( fromString )
data Session = Session Handle
deriving Show
data Result = Result { info :: String, content :: String }
deriving Show
-- | Connects to the BaseX server at host:port and establishes a session
-- with the given user name and password.
connect :: String -- ^ host name / IP
-> PortNumber -- ^ port
-> String -- ^ user name
-> String -- ^ password
-> IO (Maybe Session)
connect host port user pass = do
h <- connectTo host (PortNumber port)
hSetBuffering h (BlockBuffering $ Just 4096)
ts <- readString h
writeString h user
writeString h $ md5 (md5 pass ++ ts)
success <- ('\0' ==) <$> hGetChar h
return $ if success
then Just $ Session h
else Nothing
where md5 = show . MD5.md5 . fromString
-- | Executes a database command on the server and returns the result.
execute :: Session -- ^ BaseX session
-> String -- ^ db command
-> IO (Either String Result)
execute (Session h) cmd = do
writeString h cmd
res <- readString h
inf <- readString h
success <- ('\0' ==) <$> hGetChar h
return $ if success
then Right Result { info = inf, content = res }
else Left inf
-- | Closes the connection.
close :: Session -> IO ()
close (Session h) = writeString h "exit" >> hClose h
readString :: Handle -> IO String
readString h = do
c <- hGetChar h
if c /= '\0' then (c:) <$> readString h else return []
writeString :: Handle -> String -> IO ()
writeString h str = hPutStr h str >> hPutChar h '\0' >> hFlush h
basex-7.7.2/basex-api/src/main/haskell/Example.hs 0000664 0000000 0000000 00000002162 12224530032 0021561 0 ustar 00root root 0000000 0000000 -------------------------------------------------------------------------------
-- |
-- Module : Example
-- Copyright : (C) BaseX Team 2005-12
-- License : BSD
--
-- Maintainer : leo@woerteler.de
-- Stability : experimental
-- Portability : portable
--
-- This example shows how database commands can be executed.
--
-- Documentation: http://docs.basex.org/wiki/Clients
--
-------------------------------------------------------------------------------
module Example where
import BaseXClient
import Network ( withSocketsDo )
import Data.Time.Clock ( getCurrentTime, diffUTCTime )
import Control.Applicative ( (<$>), (<*>), pure )
query :: String
query = "xquery 1 to 10"
main :: IO ()
main = withSocketsDo $ do
-- start time
start <- getCurrentTime
-- connect to the server
(Just session) <- connect "localhost" 1984 "admin" "admin"
-- execute and print the query
execute session query >>= putStrLn . either id content
-- close the session
close session
-- print time difference
(diffUTCTime <$> getCurrentTime <*> pure start) >>= print
basex-7.7.2/basex-api/src/main/java/ 0000775 0000000 0000000 00000000000 12224530032 0017127 5 ustar 00root root 0000000 0000000 basex-7.7.2/basex-api/src/main/java/org/ 0000775 0000000 0000000 00000000000 12224530032 0017716 5 ustar 00root root 0000000 0000000 basex-7.7.2/basex-api/src/main/java/org/basex/ 0000775 0000000 0000000 00000000000 12224530032 0021020 5 ustar 00root root 0000000 0000000 basex-7.7.2/basex-api/src/main/java/org/basex/BaseXHTTP.java 0000664 0000000 0000000 00000031100 12224530032 0023360 0 ustar 00root root 0000000 0000000 package org.basex;
import static org.basex.core.Text.*;
import static org.basex.http.HTTPText.*;
import java.io.*;
import java.net.*;
import javax.net.ssl.*;
import org.basex.core.*;
import org.basex.http.*;
import org.basex.io.*;
import org.basex.server.*;
import org.basex.util.*;
import org.eclipse.jetty.server.*;
import org.eclipse.jetty.server.nio.*;
import org.eclipse.jetty.server.ssl.*;
import org.eclipse.jetty.webapp.*;
import org.eclipse.jetty.xml.*;
/**
* This is the main class for the starting the database HTTP services.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
* @author Dirk Kirsten
*/
public final class BaseXHTTP {
/** Database context. */
private final Context context;
/** HTTP port. */
private int httpPort;
/** HTTP server. */
private final Server jetty;
/** Start as daemon. */
private boolean service;
/** Stopped flag. */
private boolean stopped;
/**
* Main method, launching the HTTP services.
* Command-line arguments are listed with the {@code -h} argument.
* @param args command-line arguments
*/
public static void main(final String... args) {
try {
new BaseXHTTP(args);
} catch(final Exception ex) {
Util.errln(ex);
System.exit(1);
}
}
/**
* Constructor.
* @param args command-line arguments
* @throws Exception exception
*/
public BaseXHTTP(final String... args) throws Exception {
parseArguments(args);
// context must be initialized after parsing of arguments
context = HTTPContext.init();
// create jetty instance and set default context to HTTP path
final MainProp mprop = context.mprop;
final String webapp = mprop.get(MainProp.WEBPATH);
final WebAppContext wac = new WebAppContext(webapp, "/");
jetty = (Server) new XmlConfiguration(initJetty(webapp).inputStream()).configure();
jetty.setHandler(wac);
// set the first http port (can also be https) to the port provided by command line
if(httpPort != 0) {
for(final Connector c : jetty.getConnectors()) {
if(c instanceof SelectChannelConnector) {
c.setPort(httpPort);
break;
}
}
}
// stop server
final String startX = HTTP + ' ' + SRV_STARTED_PORT_X;
final String stopX = HTTP + ' ' + SRV_STOPPED_PORT_X;
if(stopped) {
stop();
for(final Connector c : jetty.getConnectors())
Util.outln(stopX, c.getPort());
// temporary console windows: keep the message visible for a while
Performance.sleep(1000);
return;
}
// start web server in a new process
if(service) {
final Connector connector = jetty.getConnectors()[0];
start(connector.getPort(), connector instanceof SslSelectChannelConnector, args);
for(final Connector c : jetty.getConnectors()) {
Util.outln(startX, c.getPort());
}
// temporary console windows: keep the message visible for a while
Performance.sleep(1000);
return;
}
// request password on command line if only the user was specified
if(!AProp.getSystem(MainProp.USER).isEmpty()) {
while(AProp.getSystem(MainProp.PASSWORD).isEmpty()) {
Util.out(PASSWORD + COLS);
AProp.setSystem(MainProp.PASSWORD, Util.password());
}
}
// start web server
jetty.start();
for(final Connector c : jetty.getConnectors()) {
Util.outln(startX, c.getPort());
}
// initialize web.xml settings, assign system properties and run database server
// if not done so already. this must be called after starting jetty
HTTPContext.init(wac.getServletContext());
// start daemon for stopping web server
final int stop = mprop.num(MainProp.STOPPORT);
if(stop >= 0) new StopServer(mprop.get(MainProp.SERVERHOST), stop).start();
// show info when HTTP server is aborted
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
for(final Connector c : jetty.getConnectors()) {
Util.outln(stopX, c.getPort());
}
final Log l = context.log;
if(l != null) {
for(final Connector c : jetty.getConnectors()) {
l.writeServer(OK, Util.info(stopX, c.getPort()));
}
}
context.close();
}
});
// log server start at very end (logging flag could have been updated by web.xml)
for(final Connector c : jetty.getConnectors()) {
context.log.writeServer(OK, Util.info(startX, c.getPort()));
}
}
/**
* Stops the server.
* @throws Exception exception
*/
public void stop() throws Exception {
// notify the jetty monitor to stop
final MainProp mprop = context.mprop;
final int stop = num(MainProp.STOPPORT, mprop);
if(stop >= 0) stop(stop);
// server has been started in a separate process and needs to be stopped
if(!bool(MainProp.HTTPLOCAL, mprop)) {
final int port = num(MainProp.SERVERPORT, mprop);
final int eport = num(MainProp.EVENTPORT, mprop);
BaseXServer.stop(port, eport);
}
}
/**
* Returns a numeric value for the specified option.
* @param option option to be retrieved
* @param mprop main properties
* @return numeric value
*/
private static int num(final Object[] option, final MainProp mprop) {
final String val = AProp.getSystem(option);
return val.isEmpty() ? mprop.num(option) : Token.toInt(val);
}
/**
* Returns a boolean value for the specified option.
* @param option option to be retrieved
* @param mprop main properties
* @return boolean value
*/
private static boolean bool(final Object[] option, final MainProp mprop) {
final String val = AProp.getSystem(option);
return val.isEmpty() ? mprop.is(option) : Boolean.parseBoolean(val);
}
/**
* Returns a reference to the Jetty configuration file.
* @param root target root directory
* @return input stream
* @throws IOException I/O exception
*/
private static IOFile initJetty(final String root) throws IOException {
locate(WEBCONF, root);
return locate(JETTYCONF, root);
}
/**
* Locates the specified configuration file.
* @param file file to be copied
* @param root target root directory
* @return reference to created file
* @throws IOException I/O exception
*/
private static IOFile locate(final String file, final String root) throws IOException {
final IOFile trg = new IOFile(root + '/' + file);
final boolean create = !trg.exists();
// try to locate file from development branch
final IO in = new IOFile("src/main/webapp/" + file);
final byte[] data;
if(in.exists()) {
data = in.read();
// check if resource path exists
IOFile res = new IOFile("src/main/resources/");
if(res.exists()) {
res = new IOFile(res, file);
// update file in resource path if it has changed
if(!res.exists() || !Token.eq(data, res.read())) {
Util.errln("Updating " + res);
res.dir().md();
res.write(in.read());
}
}
} else if(create) {
// try to locate file from resource path
final InputStream is = BaseXHTTP.class.getResourceAsStream('/' + file);
if(is == null) throw new BaseXException(in + " not found.");
data = new IOStream(is).read();
} else {
return trg;
}
if(create) {
// create configuration file
Util.errln("Creating " + trg);
trg.dir().md();
trg.write(data);
}
return trg;
}
/**
* Parses the command-line arguments, specified by the user.
* @param args command-line arguments
* @throws IOException I/O exception
*/
private void parseArguments(final String[] args) throws IOException {
/* command-line properties not be stored in system properties (instead of
* context.mprop). this way, they will not be overwritten by web.xml settings. */
final Args arg = new Args(args, this, HTTPINFO, Util.info(CONSOLE, HTTP));
boolean daemon = false;
while(arg.more()) {
if(arg.dash()) {
switch(arg.next()) {
case 'd': // activate debug mode
AProp.setSystem(MainProp.DEBUG, true);
Prop.debug = true;
break;
case 'D': // hidden flag: daemon mode
daemon = true;
break;
case 'e': // parse event port
AProp.setSystem(MainProp.EVENTPORT, arg.number());
break;
case 'h': // parse HTTP port
httpPort = arg.number();
break;
case 'l': // use local mode
AProp.setSystem(MainProp.HTTPLOCAL, true);
break;
case 'n': // parse host name
AProp.setSystem(MainProp.HOST, arg.string());
break;
case 'p': // parse server port
final int p = arg.number();
AProp.setSystem(MainProp.PORT, p);
AProp.setSystem(MainProp.SERVERPORT, p);
break;
case 'P': // specify password
AProp.setSystem(MainProp.PASSWORD, arg.string());
break;
case 's': // parse stop port
AProp.setSystem(MainProp.STOPPORT, arg.number());
break;
case 'S': // set service flag
service = !daemon;
break;
case 'U': // specify user name
AProp.setSystem(MainProp.USER, arg.string());
break;
case 'z': // suppress logging
AProp.setSystem(MainProp.LOG, false);
break;
default:
arg.usage();
}
} else {
if(!arg.string().equalsIgnoreCase("stop")) arg.usage();
stopped = true;
}
}
}
// STATIC METHODS ===========================================================
/**
* Starts the HTTP server in a separate process.
* @param port server port
* @param ssl encryption via HTTPS
* @param args command-line arguments
* @throws BaseXException database exception
*/
private static void start(final int port, final boolean ssl, final String... args)
throws BaseXException {
Util.start(BaseXHTTP.class, args);
// try to connect to the new server instance
for(int c = 1; c < 10; ++c) {
if(ping(LOCALHOST, port, ssl)) return;
Performance.sleep(c * 100);
}
throw new BaseXException(CONNECTION_ERROR);
}
/**
* Generates a stop file for the specified port.
* @param port server port
* @return stop file
*/
private static File stopFile(final int port) {
return new File(Prop.TMP, Util.name(BaseXHTTP.class) + port);
}
/**
* Stops the server.
* @param port server port
* @throws IOException I/O exception
*/
private static void stop(final int port) throws IOException {
final File stop = stopFile(port);
try {
stop.createNewFile();
new Socket(LOCALHOST, port).close();
// give the notified process some time to quit
Performance.sleep(100);
} catch(final IOException ex) {
stop.delete();
throw ex;
}
}
/**
* Checks if a server is running.
* @param host host
* @param port server port
* @param ssl encryption via HTTPS
* @return boolean success
*/
private static boolean ping(final String host, final int port, final boolean ssl) {
try {
// create connection
final URL url = new URL((ssl ? "https://" : "http://") + host + ':' + port);
url.openConnection().getInputStream();
return true;
} catch(final IOException ex) {
// if page is not found, server is running
// if SSL handshake failed server is running, otherwise SSLException
return ex instanceof FileNotFoundException || ex instanceof SSLHandshakeException;
}
}
/** Monitor for stopping the Jetty server. */
@SuppressWarnings("synthetic-access")
private final class StopServer extends Thread {
/** Server socket. */
private final ServerSocket ss;
/** Stop file. */
private final File stop;
/**
* Constructor.
* @param host host address
* @param port stop port
* @throws IOException I/O exception
*/
StopServer(final String host, final int port) throws IOException {
final InetAddress addr = host.isEmpty() ? null : InetAddress.getByName(host);
ss = new ServerSocket();
ss.setReuseAddress(true);
ss.bind(new InetSocketAddress(addr, port));
stop = stopFile(port);
setDaemon(true);
}
@Override
public void run() {
try {
while(true) {
ss.accept().close();
if(stop.exists()) {
ss.close();
stop.delete();
jetty.stop();
break;
}
}
} catch(final Exception ex) {
Util.errln(ex);
}
}
}
}
basex-7.7.2/basex-api/src/main/java/org/basex/api/ 0000775 0000000 0000000 00000000000 12224530032 0021571 5 ustar 00root root 0000000 0000000 basex-7.7.2/basex-api/src/main/java/org/basex/api/xmldb/ 0000775 0000000 0000000 00000000000 12224530032 0022677 5 ustar 00root root 0000000 0000000 basex-7.7.2/basex-api/src/main/java/org/basex/api/xmldb/BXCollection.java 0000664 0000000 0000000 00000020410 12224530032 0026064 0 ustar 00root root 0000000 0000000 package org.basex.api.xmldb;
import static org.basex.core.Text.*;
import java.io.*;
import java.lang.reflect.*;
import org.basex.build.*;
import org.basex.build.xml.*;
import org.basex.core.*;
import org.basex.core.cmd.*;
import org.basex.data.*;
import org.basex.data.atomic.*;
import org.basex.io.*;
import org.basex.util.*;
import org.basex.util.list.*;
import org.w3c.dom.*;
import org.xmldb.api.base.*;
import org.xmldb.api.modules.*;
/**
* Implementation of the Collection Interface for the XMLDB:API.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
public final class BXCollection implements Collection, BXXMLDBText {
/** Database context. */
final BXDatabase db;
/** Database context. */
Context ctx;
/**
* Constructor to create/open a collection.
* @param name name of the database
* @param open open existing database
* @param d database context
* @throws XMLDBException exception
*/
public BXCollection(final String name, final boolean open, final Database d)
throws XMLDBException {
db = (BXDatabase) d;
ctx = db.ctx;
try {
ctx.openDB(open ? Open.open(name, ctx) :
CreateDB.create(name, Parser.emptyParser(ctx.prop), ctx));
} catch(final IOException ex) {
throw new XMLDBException(ErrorCodes.VENDOR_ERROR, ex.getMessage());
}
}
@Override
public String getName() {
return ctx.data().meta.name;
}
@Override
public Service[] getServices() throws XMLDBException {
check();
return new Service[] {
getService(BXQueryService.XPATH, "1.0"),
getService(BXQueryService.XQUERY, "1.0"),
getService(BXCollectionManagementService.MANAGEMENT, "1.0") };
}
@Override
public Service getService(final String nm, final String ver) throws XMLDBException {
check();
if(ver.equals("1.0")) {
if(Token.eq(nm, BXQueryService.XPATH, BXQueryService.XQUERY))
return new BXQueryService(this, nm, ver);
if(nm.equals(BXCollectionManagementService.MANAGEMENT))
return new BXCollectionManagementService(this);
}
return null;
}
@Override
public Collection getParentCollection() throws XMLDBException {
check();
return null;
}
@Override
public Collection getChildCollection(final String name) throws XMLDBException {
check();
return null;
}
@Override
public int getChildCollectionCount() throws XMLDBException {
check();
return 0;
}
@Override
public String[] listChildCollections() throws XMLDBException {
check();
return new String[] {};
}
@Override
public int getResourceCount() throws XMLDBException {
check();
return ctx.data().resources.docs().size();
}
@Override
public String[] listResources() throws XMLDBException {
check();
final StringList sl = new StringList();
final Data data = ctx.data();
final IntList il = data.resources.docs();
final int is = il.size();
for(int i = 0; i < is; i++) sl.add(Token.string(data.text(il.get(i), true)));
return sl.toArray();
}
@Override
public BXXMLResource createResource(final String id, final String type)
throws XMLDBException {
check();
if(type.equals(XMLResource.RESOURCE_TYPE)) {
// create new id, if necessary
final String uid = id == null || id.isEmpty() ? createId() : id;
return new BXXMLResource(null, 0, uid, this);
}
// reject binary and other resources
throw type.equals(BinaryResource.RESOURCE_TYPE) ?
new XMLDBException(ErrorCodes.VENDOR_ERROR, ERR_BINARY) :
new XMLDBException(ErrorCodes.UNKNOWN_RESOURCE_TYPE, ERR_TYPE + type);
}
@Override
public void removeResource(final Resource res) throws XMLDBException {
check();
// check if the resource is an xml resource
final BXXMLResource del = checkXML(res);
final Data data = ctx.data();
// check if data instance refers to another database
if(del.data != data && del.data != null) throw new XMLDBException(
ErrorCodes.NO_SUCH_RESOURCE, ERR_UNKNOWN + data.meta.name);
if(!data.startUpdate()) throw new XMLDBException(ErrorCodes.VENDOR_ERROR, ERR_LOCK);
data.delete(getResource(del.getId()).pos);
ctx.update();
data.finishUpdate();
}
@Override
public void storeResource(final Resource res) throws XMLDBException {
check();
// check if resource has any contents
final BXXMLResource xml = checkXML(res);
if(res.getContent() == null)
throw new XMLDBException(ErrorCodes.INVALID_RESOURCE, ERR_EMPTY);
// disallow storage of resources without id
final String id = res.getId();
if(id == null) throw new XMLDBException(ErrorCodes.INVALID_RESOURCE, ERR_ID);
// document exists - delete old one first
final Resource old = getResource(id);
if(old != null) removeResource(getResource(id));
// create parser, dependent on input type
final Object cont = xml.content;
// insert document
final Data md;
try {
final Parser p = cont instanceof Document ?
new DOMWrapper((Document) cont, id, ctx.prop) :
Parser.singleParser(new IOContent((byte[]) cont, id), ctx.prop, "");
md = MemBuilder.build(id, p);
} catch(final IOException ex) {
throw new XMLDBException(ErrorCodes.INVALID_RESOURCE, ex.getMessage());
}
final Data data = ctx.data();
if(!data.startUpdate()) throw new XMLDBException(ErrorCodes.VENDOR_ERROR, ERR_LOCK);
data.insert(data.meta.size, -1, new DataClip(md));
ctx.update();
data.finishUpdate();
}
@Override
public BXXMLResource getResource(final String id) throws XMLDBException {
check();
if(id == null) return null;
final Data data = ctx.data();
final int pre = data.resources.doc(id);
return pre == -1 ? null : new BXXMLResource(data, pre, id, this);
}
@Override
public String createId() throws XMLDBException {
final String[] res = listResources();
String id;
do {
id = Long.toString(System.currentTimeMillis());
} while(exists(res, id));
return id;
}
@Override
public boolean isOpen() {
return ctx != null;
}
@Override
public void close() {
if(ctx != null) ctx.close();
ctx = null;
}
@Override
public String getProperty(final String key) throws XMLDBException {
check();
try {
return MetaData.class.getField(key).get(ctx.data().meta).toString();
} catch(final Exception ex) {
return null;
}
}
@Override
public void setProperty(final String key, final String val) throws XMLDBException {
check();
try {
final MetaData md = ctx.data().meta;
final Field f = MetaData.class.getField(key);
final Object k = f.get(md);
if(k instanceof Boolean) {
final boolean b = val == null ? !(Boolean) k :
val.equalsIgnoreCase(TRUE);
f.setBoolean(md, b);
} else if(k instanceof Integer) {
f.setInt(md, Integer.parseInt(val));
} else {
f.set(md, val);
}
} catch(final Exception ex) {
throw new XMLDBException(ErrorCodes.VENDOR_ERROR, ERR_PROP + key);
}
}
/**
* Checks if the specified id exists in the specified id list.
* @param list id list
* @param id id to be found
* @return result of check
*/
private static boolean exists(final String[] list, final String id) {
for(final String l : list) if(l.equals(id)) return true;
return false;
}
/**
* Checks if the collection is currently open.
* @throws XMLDBException exception
*/
private void check() throws XMLDBException {
if(ctx == null) throw new XMLDBException(ErrorCodes.COLLECTION_CLOSED);
}
/**
* Returns the specified resource as a project specific XML resource.
* If that's not possible, throws an exception
* @param res input resource
* @return xml resource
* @throws XMLDBException exception
*/
private static BXXMLResource checkXML(final Resource res) throws XMLDBException {
if(!(res instanceof BXXMLResource)) {
throw new XMLDBException(ErrorCodes.NO_SUCH_RESOURCE, ERR_UNKNOWN + res);
}
return (BXXMLResource) res;
}
}
basex-7.7.2/basex-api/src/main/java/org/basex/api/xmldb/BXCollectionManagementService.java 0000664 0000000 0000000 00000003650 12224530032 0031411 0 ustar 00root root 0000000 0000000 package org.basex.api.xmldb;
import org.basex.core.*;
import org.basex.core.cmd.*;
import org.xmldb.api.base.*;
import org.xmldb.api.modules.*;
/**
* Implementation of the CollectionManagementService Interface for the
* XMLDB:API. Note that a database has one collection at a time,
* so creating a new collection creates a new database as well, and the
* specified collection reference is reset every time a database is created.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
final class BXCollectionManagementService implements
CollectionManagementService, BXXMLDBText {
/** Service constant. */
static final String MANAGEMENT = "CollectionManagementService";
/** Service constant. */
private static final String VERSION = "1.0";
/** Collection reference. */
private BXCollection coll;
/**
* Default constructor.
* @param c collection reference
*/
BXCollectionManagementService(final BXCollection c) {
coll = c;
}
@Override
public Collection createCollection(final String name) throws XMLDBException {
return new BXCollection(name, false, coll.db);
}
@Override
public void removeCollection(final String name) throws XMLDBException {
try {
new DropDB(name).execute(coll.ctx);
} catch(final BaseXException ex) {
throw new XMLDBException(ErrorCodes.VENDOR_ERROR, ex.getMessage());
}
}
@Override
public String getName() {
return MANAGEMENT;
}
@Override
public String getVersion() {
return VERSION;
}
@Override
public void setCollection(final Collection c) {
coll = (BXCollection) c;
}
@Override
public String getProperty(final String nm) {
return null;
}
@Override
public void setProperty(final String nm, final String value) throws XMLDBException {
throw new XMLDBException(ErrorCodes.VENDOR_ERROR, ERR_PROP + nm);
}
}
basex-7.7.2/basex-api/src/main/java/org/basex/api/xmldb/BXDatabase.java 0000664 0000000 0000000 00000004645 12224530032 0025511 0 ustar 00root root 0000000 0000000 package org.basex.api.xmldb;
import static org.basex.core.Text.*;
import java.util.*;
import org.basex.core.*;
import org.basex.core.cmd.Set;
import org.xmldb.api.base.*;
import org.xmldb.api.base.Collection;
/**
* Implementation of the Database Interface for the XMLDB:API.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
public final class BXDatabase implements Database, BXXMLDBText {
/** Database context. */
public final Context ctx = new Context();
@Override
public boolean acceptsURI(final String uri) throws XMLDBException {
getCollectionName(uri);
return true;
}
@Override
public Collection getCollection(final String uri, final String user,
final String password) throws XMLDBException {
// create database context
final String name = getCollectionName(uri);
final boolean exists = ctx.mprop.dbexists(name);
return exists ? new BXCollection(name, true, this) : null;
}
@Override
public String getConformanceLevel() {
return CONFORMANCE_LEVEL;
}
@Override
public String getName() {
return NAMELC;
}
@Override
public String getProperty(final String key) {
try {
final String prop = key.toUpperCase(Locale.ENGLISH);
return ((Object[]) Prop.class.getField(prop).get(null))[1].toString();
} catch(final Exception ex) {
return null;
}
}
@Override
public void setProperty(final String key, final String value) throws XMLDBException {
try {
new Set(key, value).execute(ctx);
} catch(final BaseXException ex) {
throw new XMLDBException(ErrorCodes.VENDOR_ERROR, ERR_PROP + key);
}
}
/**
* Returns the name of a collection.
* @param uri input uri
* @return collection name
* @throws XMLDBException exception
*/
private String getCollectionName(final String uri) throws XMLDBException {
// try to extract name of collection; otherwise, throw exception
if(uri != null) {
final String main = uri.startsWith(XMLDBC) ? uri : XMLDBC + uri;
if(main.startsWith(XMLDBURI)) {
final String host = main.substring(XMLDBURI.length());
final String lh = LOCALHOST + ':' + ctx.mprop.num(MainProp.SERVERPORT) + '/';
if(host.startsWith(lh)) return host.substring(lh.length());
}
}
throw new XMLDBException(ErrorCodes.INVALID_URI, ERR_URI + uri);
}
}
basex-7.7.2/basex-api/src/main/java/org/basex/api/xmldb/BXQueryService.java 0000664 0000000 0000000 00000006670 12224530032 0026433 0 ustar 00root root 0000000 0000000 package org.basex.api.xmldb;
import static org.basex.util.Token.*;
import java.util.*;
import org.basex.data.*;
import org.basex.query.*;
import org.xmldb.api.base.*;
import org.xmldb.api.base.Collection;
import org.xmldb.api.modules.*;
/**
* Abstract QueryService definition for the XMLDB:API.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
final class BXQueryService implements XPathQueryService, BXXMLDBText {
/** XPath service constant. */
static final String XPATH = "XPathQueryService";
/** XQuery service constant. */
static final String XQUERY = "XQueryQueryService";
/** Namespaces. */
private final HashMap ns = new HashMap();
/** Service name. */
private final String name;
/** Service version. */
private final String version;
/** Collection reference. */
private BXCollection coll;
/**
* Standard constructor.
* @param c for collection reference
* @param n service name
* @param v version
*/
BXQueryService(final BXCollection c, final String n, final String v) {
coll = c;
name = n;
version = v;
}
@Override
public void setNamespace(final String pre, final String uri) throws XMLDBException {
if(uri != null && !uri.isEmpty()) ns.put(pre == null ? "" : pre, uri);
else throw new XMLDBException(ErrorCodes.VENDOR_ERROR, ERR_NSURI + pre);
}
@Override
public String getNamespace(final String pre) {
return ns.get(pre == null ? "" : pre);
}
@Override
public void removeNamespace(final String pre) {
ns.remove(pre == null ? "" : pre);
}
@Override
public void clearNamespaces() {
ns.clear();
}
@Override
public BXResourceSet query(final String query) throws XMLDBException {
return query(coll.ctx.current(), query);
}
@Override
public BXResourceSet queryResource(final String id, final String query)
throws XMLDBException {
final BXXMLResource xml = coll.getResource(id);
if(xml != null) return query(new Nodes(xml.pos, xml.data), query);
// throw exception if id was not found...
throw new XMLDBException(ErrorCodes.VENDOR_ERROR, ERR_RES + id);
}
@Override
public String getName() {
return name;
}
@Override
public String getVersion() {
return version;
}
@Override
public void setCollection(final Collection col) {
coll = (BXCollection) col;
}
@Override
public String getProperty(final String nm) {
return null;
}
@Override
public void setProperty(final String nm, final String value) throws XMLDBException {
throw new XMLDBException(ErrorCodes.VENDOR_ERROR, ERR_PROP + nm);
}
/**
* Method for both query actions.
* @param nodes initial node set
* @param query query string
* @return resource set
* @throws XMLDBException exception
*/
private BXResourceSet query(final Nodes nodes, final String query)
throws XMLDBException {
// creates a query instance
final QueryProcessor qp = new QueryProcessor(query, coll.ctx).context(nodes);
try {
coll.ctx.register(qp);
// add default namespaces
for(final String n : ns.keySet()) {
qp.ctx.sc.ns.add(token(n), token(ns.get(n)), null);
}
// perform query and return result
return new BXResourceSet(qp.execute(), coll);
} catch(final QueryException ex) {
throw new XMLDBException(ErrorCodes.VENDOR_ERROR, ex.getMessage());
} finally {
qp.close();
coll.ctx.unregister(qp);
}
}
}
basex-7.7.2/basex-api/src/main/java/org/basex/api/xmldb/BXResourceIterator.java 0000664 0000000 0000000 00000001653 12224530032 0027302 0 ustar 00root root 0000000 0000000 package org.basex.api.xmldb;
import java.util.*;
import org.xmldb.api.base.*;
/**
* Implementation of the ResourceIterator Interface for the XMLDB:API.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
final class BXResourceIterator implements ResourceIterator, BXXMLDBText,
Iterable {
/** Resources. */
private final Iterator res;
/**
* Standard constructor with result.
* @param r resources
*/
BXResourceIterator(final ArrayList r) {
res = r.iterator();
}
@Override
public boolean hasMoreResources() {
return res.hasNext();
}
@Override
public Resource nextResource() throws XMLDBException {
if(!res.hasNext())
throw new XMLDBException(ErrorCodes.NO_SUCH_RESOURCE, ERR_ITER);
return res.next();
}
@Override
public Iterator iterator() {
return res;
}
}
basex-7.7.2/basex-api/src/main/java/org/basex/api/xmldb/BXResourceSet.java 0000664 0000000 0000000 00000003503 12224530032 0026240 0 ustar 00root root 0000000 0000000 package org.basex.api.xmldb;
import java.util.*;
import org.basex.data.*;
import org.basex.util.*;
import org.xmldb.api.base.*;
import org.xmldb.api.base.Collection;
/**
* Implementation of the ResourceSet Interface for the XMLDB:API.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
final class BXResourceSet implements ResourceSet, BXXMLDBText {
/** Resources. */
private final ArrayList res;
/** Collection reference. */
private final Collection coll;
/**
* Default constructor with result.
* @param r result
* @param c collection
*/
BXResourceSet(final Result r, final Collection c) {
// convert result into resource instances
res = new ArrayList((int) r.size());
for(int s = 0; s < r.size(); ++s) res.add(new BXXMLResource(r, s, c));
coll = c;
}
@Override
public Resource getResource(final long i) throws XMLDBException {
if(i >= 0 && i < res.size()) return res.get((int) i);
throw new XMLDBException(ErrorCodes.NO_SUCH_RESOURCE);
}
@Override
public void addResource(final Resource r) {
res.add(r);
}
@Override
public void removeResource(final long index) {
res.remove((int) index);
}
@Override
public BXResourceIterator getIterator() {
return new BXResourceIterator(res);
}
@Override
public Resource getMembersAsResource() throws XMLDBException {
final TokenBuilder tb = new TokenBuilder().add('<').add(XMLDB).add('>');
for(final Resource r : getIterator()) {
tb.add(r.getContent().toString());
}
return new BXXMLResource(tb.add('<').add('/').add(XMLDB).add('>').finish(), coll);
}
@Override
public long getSize() {
return res.size();
}
@Override
public void clear() {
res.clear();
}
}
basex-7.7.2/basex-api/src/main/java/org/basex/api/xmldb/BXXMLDBText.java 0000664 0000000 0000000 00000002743 12224530032 0025515 0 ustar 00root root 0000000 0000000 package org.basex.api.xmldb;
import static org.basex.core.Text.*;
/**
* This class organizes textual information for the XMLDB API.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
interface BXXMLDBText {
/** DB URI. */
String DBURI = NAMELC + "://";
/** XMLDB Prefix. */
String XMLDB = "xmldb";
/** XMLDB with colon. */
String XMLDBC = XMLDB + ':';
/** XMLDB URI. */
String XMLDBURI = XMLDBC + DBURI;
/** Conformance level of the implementation. */
String CONFORMANCE_LEVEL = "0";
/** Error message. */
String ERR_URI = "Invalid URI: ";
/** Error message. */
String ERR_PROP = "Property could not be set: ";
/** Error message. */
String ERR_BINARY = "Binary resources not supported.";
/** Error message. */
String ERR_TYPE = "Resource type is unknown: ";
/** Error message. */
String ERR_EMPTY = "Resource has no contents.";
/** Error message. */
String ERR_ID = "Resource has no ID.";
/** Error message. */
String ERR_UNKNOWN = "Unknown Resource: ";
/** Error message. */
String ERR_CONT = "Content cannot be set.";
/** Error message. */
String ERR_NSURI = "Namespace URI is empty: ";
/** Error message. */
String ERR_RES = "Resource not found: ";
/** Error message. */
String ERR_ITER = "Resource pointer out of range.";
/** Error message. */
String ERR_DOC = "Document ID cannot be retrieved from query result.";
/** Error message. */
String ERR_LOCK = "Database cannot be marked as 'updating'.";
}
basex-7.7.2/basex-api/src/main/java/org/basex/api/xmldb/BXXMLResource.java 0000664 0000000 0000000 00000014142 12224530032 0026146 0 ustar 00root root 0000000 0000000 package org.basex.api.xmldb;
import static org.basex.util.Token.*;
import java.io.*;
import javax.xml.parsers.*;
import org.basex.api.dom.*;
import org.basex.build.*;
import org.basex.build.Parser;
import org.basex.build.xml.*;
import org.basex.core.*;
import org.basex.data.*;
import org.basex.io.*;
import org.basex.io.out.*;
import org.basex.io.serial.*;
import org.basex.query.*;
import org.basex.query.value.node.*;
import org.w3c.dom.*;
import org.xml.sax.*;
import org.xmldb.api.base.*;
import org.xmldb.api.modules.*;
/**
* Implementation of the XMLResource Interface for the XMLDB:API.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
final class BXXMLResource implements XMLResource, BXXMLDBText {
/** Collection reference. */
private final Collection coll;
/** String id. */
private String id;
/** Query result. */
private Result result;
/** Cached content. */
Object content;
/** Data reference. */
Data data;
/** Pre value or result position. */
int pos;
/**
* Constructor for generated results.
* @param d content data
* @param c Collection
*/
BXXMLResource(final byte[] d, final Collection c) {
content = d;
coll = c;
}
/**
* Constructor for query results.
* @param res query result
* @param p query counter
* @param c Collection
*/
BXXMLResource(final Result res, final int p, final Collection c) {
result = res;
coll = c;
pos = p;
}
/**
* Standard constructor.
* @param d data reference
* @param p pre value
* @param i id
* @param c collection
*/
BXXMLResource(final Data d, final int p, final String i, final Collection c) {
id = i;
coll = c;
data = d;
pos = p;
}
@Override
public Collection getParentCollection() {
return coll;
}
@Override
public String getId() {
return id;
}
@Override
public String getResourceType() {
return XMLResource.RESOURCE_TYPE;
}
@Override
public Object getContent() throws XMLDBException {
if(content == null) {
try {
// serialize and cache content
final ArrayOutput ao = new ArrayOutput();
final Serializer ser = Serializer.get(ao);
if(data != null) {
ser.serialize(new DBNode(data, pos));
} else if(result != null) {
result.serialize(ser, pos);
} else {
return null;
}
content = ao.toArray();
} catch(final IOException ex) {
throw new XMLDBException(ErrorCodes.VENDOR_ERROR, ex.getMessage());
}
}
return content instanceof byte[] ? string((byte[]) content) : content;
}
@Override
public void setContent(final Object value) throws XMLDBException {
// allow only strings, byte arrays and {@link File} instances
if(value instanceof byte[]) {
content = value;
} else if(value instanceof String) {
content = token(value.toString());
} else if(value instanceof File) {
try {
content = new IOFile((File) value).read();
} catch(final IOException ex) {
throw new XMLDBException(ErrorCodes.VENDOR_ERROR, ERR_CONT +
'\n' + ex.getMessage());
}
} else {
throw new XMLDBException(ErrorCodes.VENDOR_ERROR, ERR_CONT);
}
}
@Override
public String getDocumentId() throws XMLDBException {
// throw exception if resource result from query; does not conform to the
// specs, but many query results are not related to a document anymore
if(result != null)
throw new XMLDBException(ErrorCodes.VENDOR_ERROR, ERR_DOC);
// resource does not result from a query - return normal id
if(id != null) return id;
// get document root id
int p = pos;
while(p >= 0) {
final int k = data.kind(p);
if(k == Data.DOC) return string(data.text(p, true));
p = data.parent(p, k);
}
return null;
}
@Override
public Node getContentAsDOM() {
if(!(content instanceof Node)) content = new BXDoc(new DBNode(data, pos));
return (Node) content;
}
@Override
public void setContentAsDOM(final Node cont) throws XMLDBException {
// allow only document instances...
if(cont == null) throw new XMLDBException(ErrorCodes.INVALID_RESOURCE);
if(cont instanceof Document) content = cont;
else throw new XMLDBException(ErrorCodes.WRONG_CONTENT_TYPE);
}
@Override
public void getContentAsSAX(final ContentHandler handler) throws XMLDBException {
if(handler == null) throw new XMLDBException(ErrorCodes.INVALID_RESOURCE);
final SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(true);
factory.setValidating(false);
try {
// caching should be avoided and replaced by a stream reader...
final XMLReader reader = factory.newSAXParser().getXMLReader();
reader.setContentHandler(handler);
reader.parse(new InputSource(new StringReader(getContent().toString())));
} catch(final Exception pce) {
throw new XMLDBException(ErrorCodes.VENDOR_ERROR, pce.getMessage());
}
}
@Override
public ContentHandler setContentAsSAX() throws XMLDBException {
// ..might be replaced by a custom SAX content handler in future
final MemBuilder mb = new MemBuilder("", Parser.emptyParser(new Prop()));
mb.init();
return new BXSAXContentHandler(this, mb);
}
/** SAX parser. */
private static final class BXSAXContentHandler extends SAXHandler {
/** XMLResource. */
private final BXXMLResource res;
/**
* Default constructor.
* @param mb memory builder
* @param r resource
*/
BXSAXContentHandler(final BXXMLResource r, final MemBuilder mb) {
super(mb, false, false);
res = r;
}
@Override
public void endDocument() throws SAXException {
try {
res.content = new DBNode(((MemBuilder) builder).data()).serialize().toArray();
} catch(final QueryException ex) {
error(new BaseXException(ex));
}
}
}
}
basex-7.7.2/basex-api/src/main/java/org/basex/api/xmldb/package.html 0000664 0000000 0000000 00000000064 12224530032 0025160 0 ustar 00root root 0000000 0000000
Implementation of the XML:DB API.
basex-7.7.2/basex-api/src/main/java/org/basex/http/ 0000775 0000000 0000000 00000000000 12224530032 0021777 5 ustar 00root root 0000000 0000000 basex-7.7.2/basex-api/src/main/java/org/basex/http/BaseXServlet.java 0000664 0000000 0000000 00000005573 12224530032 0025223 0 ustar 00root root 0000000 0000000 package org.basex.http;
import static javax.servlet.http.HttpServletResponse.*;
import static org.basex.http.HTTPText.*;
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.basex.core.*;
import org.basex.http.restxq.*;
import org.basex.query.*;
import org.basex.server.*;
import org.basex.util.*;
/**
*
Base class for all servlets.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
public abstract class BaseXServlet extends HttpServlet {
/** Servlet-specific user. */
protected String user;
/** Servlet-specific password. */
protected String pass;
@Override
public void init(final ServletConfig config) throws ServletException {
super.init(config);
try {
HTTPContext.init(config.getServletContext());
final Enumeration en = config.getInitParameterNames();
while(en.hasMoreElements()) {
String key = en.nextElement().toLowerCase(Locale.ENGLISH);
final String val = config.getInitParameter(key);
if(key.startsWith(Prop.DBPREFIX)) key = key.substring(Prop.DBPREFIX.length());
if(key.equalsIgnoreCase(MainProp.USER[0].toString())) {
user = val;
} else if(key.equalsIgnoreCase(MainProp.PASSWORD[0].toString())) {
pass = val;
}
}
} catch(final IOException ex) {
throw new ServletException(ex);
}
}
@Override
public final void service(final HttpServletRequest req, final HttpServletResponse res)
throws IOException {
final HTTPContext http = new HTTPContext(req, res, this);
final boolean restxq = this instanceof RestXqServlet;
try {
run(http);
http.log("", SC_OK);
} catch(final HTTPException ex) {
http.status(ex.getStatus(), Util.message(ex), restxq);
} catch(final LoginException ex) {
http.status(SC_UNAUTHORIZED, Util.message(ex), restxq);
} catch(final IOException ex) {
http.status(SC_BAD_REQUEST, Util.message(ex), restxq);
} catch(final QueryException ex) {
http.status(SC_BAD_REQUEST, Util.message(ex), restxq);
} catch(final Exception ex) {
final String msg = Util.bug(ex);
Util.errln(msg);
http.status(SC_INTERNAL_SERVER_ERROR, Util.info(UNEXPECTED, msg), restxq);
} finally {
if(Prop.debug) {
Util.outln("_ REQUEST _________________________________" + Prop.NL + req);
final Enumeration en = req.getHeaderNames();
while(en.hasMoreElements()) {
final String key = en.nextElement();
Util.outln(Text.LI + key + Text.COLS + req.getHeader(key));
}
Util.out("_ RESPONSE ________________________________" + Prop.NL + res);
}
http.close();
}
}
/**
* Runs the code.
* @param http HTTP context
* @throws Exception any exception
*/
protected abstract void run(final HTTPContext http) throws Exception;
}
basex-7.7.2/basex-api/src/main/java/org/basex/http/HTTPContext.java 0000664 0000000 0000000 00000027046 12224530032 0024777 0 ustar 00root root 0000000 0000000 package org.basex.http;
import static javax.servlet.http.HttpServletResponse.*;
import static org.basex.data.DataText.*;
import static org.basex.http.HTTPText.*;
import static org.basex.io.MimeTypes.*;
import static org.basex.util.Token.*;
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.basex.*;
import org.basex.core.*;
import org.basex.io.*;
import org.basex.io.serial.*;
import org.basex.server.*;
import org.basex.util.*;
import org.basex.util.list.*;
/**
* This class bundles context-based information on a single HTTP operation.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
public final class HTTPContext {
/** Servlet request. */
public final HttpServletRequest req;
/** Servlet response. */
public final HttpServletResponse res;
/** Request method. */
public final HTTPMethod method;
/** Serialization parameters. */
public String serialization = "";
/** Result wrapping. */
public boolean wrapping;
/** User name. */
public String user;
/** Singleton database context. */
private static Context context;
/** Initialization flag. */
private static boolean init;
/** Performance. */
private final Performance perf = new Performance();
/** Segments. */
private final String[] segments;
/** Current user session. */
private LocalSession session;
/** Password. */
private String pass;
/**
* Constructor.
* @param rq request
* @param rs response
* @param servlet calling servlet instance
* @throws IOException I/O exception
*/
public HTTPContext(final HttpServletRequest rq, final HttpServletResponse rs,
final BaseXServlet servlet) throws IOException {
req = rq;
res = rs;
final String mth = rq.getMethod();
method = HTTPMethod.get(mth);
final StringBuilder uri = new StringBuilder(req.getRequestURL());
final String qs = req.getQueryString();
if(qs != null) uri.append('?').append(qs);
log('[' + mth + "] " + uri, null);
// set UTF8 as default encoding (can be overwritten)
res.setCharacterEncoding(UTF8);
segments = toSegments(req.getPathInfo());
// adopt servlet-specific credentials or use global ones
final MainProp mprop = context().mprop;
user = servlet.user != null ? servlet.user : mprop.get(MainProp.USER);
pass = servlet.pass != null ? servlet.pass : mprop.get(MainProp.PASSWORD);
// overwrite credentials with session-specific data
final String auth = req.getHeader(AUTHORIZATION);
if(auth != null) {
final String[] values = auth.split(" ");
if(values[0].equals(BASIC)) {
final String[] cred = Base64.decode(values[1]).split(":", 2);
if(cred.length != 2) throw new LoginException(NOPASSWD);
user = cred[0];
pass = cred[1];
} else {
throw new LoginException(WHICHAUTH, values[0]);
}
}
}
/**
* Returns an immutable map with all query parameters.
* @return parameters
*/
public Map params() {
return req.getParameterMap();
}
/**
* Returns the content type of a request (without an optional encoding).
* @return content type
*/
public String contentType() {
final String ct = req.getContentType();
return ct != null ? ct.replaceFirst(";.*", "") : null;
}
/**
* Returns the content type extension of a request (without an optional encoding).
* @return content type
*/
public String contentTypeExt() {
final String ct = req.getContentType();
return ct != null ? ct.replaceFirst("^.*?;\\s*", "") : null;
}
/**
* Initializes the output. Sets the expected encoding and content type.
* @param sprop serialization properties
*/
public void initResponse(final SerializerProp sprop) {
// set content type and encoding
final String enc = sprop.get(SerializerProp.S_ENCODING);
res.setCharacterEncoding(enc);
final String ct = mediaType(sprop);
res.setContentType(new TokenBuilder(ct).add(CHARSET).add(enc).toString());
}
/**
* Returns the media type defined in the specified serialization properties.
* @param sprop serialization properties
* @return media type
*/
public static String mediaType(final SerializerProp sprop) {
// set content type
final String type = sprop.get(SerializerProp.S_MEDIA_TYPE);
if(!type.isEmpty()) return type;
// determine content type dependent on output method
final String mt = sprop.get(SerializerProp.S_METHOD);
if(mt.equals(M_RAW)) return APP_OCTET;
if(mt.equals(M_XML)) return APP_XML;
if(eq(mt, M_JSON, M_JSONML)) return APP_JSON;
if(eq(mt, M_XHTML, M_HTML)) return TEXT_HTML;
return TEXT_PLAIN;
}
/**
* Returns the path depth.
* @return path depth
*/
public int depth() {
return segments.length;
}
/**
* Returns a single path segment.
* @param i index
* @return segment
*/
public String segment(final int i) {
return segments[i];
}
/**
* Returns the database path (i.e., all path entries except for the first).
* @return path depth
*/
public String dbpath() {
final TokenBuilder tb = new TokenBuilder();
for(int p = 1; p < segments.length; p++) {
if(!tb.isEmpty()) tb.add('/');
tb.add(segments[p]);
}
return tb.toString();
}
/**
* Returns the addressed database (i.e., the first path entry), or {@code null}
* if the root directory was specified.
* @return database
*/
public String db() {
return depth() == 0 ? null : segments[0];
}
/**
* Returns an array with all accepted content types.
* if the root directory was specified.
* @return database
*/
public String[] produces() {
final String[] acc = req.getHeader("Accept").split("\\s*,\\s*");
for(int a = 0; a < acc.length; a++) {
if(acc[a].indexOf(';') != -1) acc[a] = acc[a].replaceAll("\\w*;.*", "");
}
return acc;
}
/**
* Sets a status and sends an info message.
* @param code status code
* @param message info message
* @param error treat as error (use web server standard output)
* @throws IOException I/O exception
*/
public void status(final int code, final String message, final boolean error)
throws IOException {
try {
log(message, code);
res.resetBuffer();
if(code == SC_UNAUTHORIZED) res.setHeader(WWW_AUTHENTICATE, BASIC);
if(error && code >= 400) {
res.sendError(code, message);
} else {
res.setStatus(code);
if(message != null) res.getOutputStream().write(token(message));
}
} catch(final IllegalStateException ex) {
log(Util.message(ex), SC_INTERNAL_SERVER_ERROR);
}
}
/**
* Updates the credentials.
* @param u user
* @param p password
*/
public void credentials(final String u, final String p) {
user = u;
pass = p;
}
/**
* Creates a new {@link LocalSession} instance.
* @return database session
* @throws IOException I/O exception
*/
public LocalSession session() throws IOException {
if(session == null) {
final byte[] address = token(req.getRemoteAddr());
try {
if(user == null || user.isEmpty() || pass == null || pass.isEmpty())
throw new LoginException(NOPASSWD);
session = new LocalSession(context(), user, pass);
context.blocker.remove(address);
} catch(final LoginException ex) {
// delay users with wrong passwords
for(int d = context.blocker.delay(address); d > 0; d--) Performance.sleep(1000);
throw ex;
}
}
return session;
}
/**
* Closes an open database session.
*/
public void close() {
if(session != null) session.close();
}
/**
* Returns the database context.
* @return context;
*/
public Context context() {
return context;
}
/**
* Writes a log message.
* @param info message info
* @param type message type (true/false/null: OK, ERROR, REQUEST, Error Code)
*/
public void log(final String info, final Object type) {
// add evaluation time if any type is specified
context.log.write(type != null ?
new Object[] { address(), context.user.name, type, info, perf } :
new Object[] { address(), context.user.name, null, info });
}
// STATIC METHODS =====================================================================
/**
* Initializes the HTTP context.
* @return context;
*/
public static synchronized Context init() {
if(context == null) context = new Context();
return context;
}
/**
* Initializes the database context, based on the initial servlet context.
* Parses all context parameters and passes them on to the database context.
* @param sc servlet context
* @throws IOException I/O exception
*/
public static synchronized void init(final ServletContext sc) throws IOException {
// check if HTTP context has already been initialized
if(init) return;
init = true;
// set web application path as home directory and HTTPPATH
final String webapp = sc.getRealPath("/");
AProp.setSystem(Prop.PATH, webapp);
AProp.setSystem(MainProp.WEBPATH, webapp);
// bind all parameters that start with "org.basex." to system properties
final Enumeration en = sc.getInitParameterNames();
while(en.hasMoreElements()) {
final String key = en.nextElement();
if(!key.startsWith(Prop.DBPREFIX)) continue;
// legacy: rewrite obsolete properties. will be removed some versions later
final String val = sc.getInitParameter(key);
String k = key;
String v = val;
if(key.equals(Prop.DBPREFIX + "httppath")) {
k = Prop.DBPREFIX + MainProp.RESTXQPATH[0];
} else if(key.equals(Prop.DBPREFIX + "mode")) {
k = Prop.DBPREFIX + MainProp.HTTPLOCAL[0];
v = Boolean.toString(v.equals("local"));
} else if(key.equals(Prop.DBPREFIX + "server")) {
k = Prop.DBPREFIX + MainProp.HTTPLOCAL[0];
v = Boolean.toString(!Boolean.parseBoolean(v));
}
k = k.toLowerCase(Locale.ENGLISH);
if(!k.equals(key) || !v.equals(val)) {
Util.errln("Warning! Outdated property: " +
key + '=' + val + " => " + k + '=' + v);
}
// prefix relative paths with absolute servlet path
if(k.endsWith("path") && !new File(v).isAbsolute()) {
Util.debug(k.toUpperCase(Locale.ENGLISH) + ": " + v);
v = new IOFile(webapp, v).path();
}
AProp.setSystem(k, v);
}
// create context, update property instances
if(context == null) {
context = new Context(false);
} else {
context.mprop.setSystem();
context.prop.setSystem();
}
// start server instance
if(!context.mprop.is(MainProp.HTTPLOCAL)) new BaseXServer(context);
}
/**
* Converts the path to a string array, containing the single segments.
* @param path path, or {@code null}
* @return path depth
*/
public static String[] toSegments(final String path) {
final StringList sl = new StringList();
if(path != null) {
final TokenBuilder tb = new TokenBuilder();
for(int s = 0; s < path.length(); s++) {
final char ch = path.charAt(s);
if(ch == '/') {
if(tb.isEmpty()) continue;
sl.add(tb.toString());
tb.reset();
} else {
tb.add(ch);
}
}
if(!tb.isEmpty()) sl.add(tb.toString());
}
return sl.toArray();
}
// PRIVATE METHODS ====================================================================
/**
* Returns a string with the remote user address.
* @return user address
*/
private String address() {
return req.getRemoteAddr() + ':' + req.getRemotePort();
}
}
basex-7.7.2/basex-api/src/main/java/org/basex/http/HTTPErr.java 0000664 0000000 0000000 00000003463 12224530032 0024100 0 ustar 00root root 0000000 0000000 package org.basex.http;
import static javax.servlet.http.HttpServletResponse.*;
/**
* This class contains all query error messages.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
public enum HTTPErr {
/** Error: 201 (created). */
CREATED_X(SC_CREATED, "%"),
/** Error: 400 (bad request). */
BAD_REQUEST_X(SC_BAD_REQUEST, "%"),
/** Error 400, "Only one operation can be specified". */
ONEOP(SC_BAD_REQUEST, "Only one operation can be specified."),
/** Error 400, "Unknown parameter: '%'". */
UNKNOWN_PARAM_X(SC_BAD_REQUEST, "Unknown parameter: '%'."),
/** Error 400, "Invalid parameters: '%'". */
INVALID_PARAM_X(SC_BAD_REQUEST, "Parameters cannot be decoded: %."),
/** Error 400, "Multiple context items specified.". */
MULTIPLE_CONTEXT_X(SC_BAD_REQUEST, "Multiple context items specified."),
/** Error: 404 (not found). */
NOT_FOUND_X(SC_NOT_FOUND, "%"),
/** Error: 404, "No path specified.". */
NO_PATH(SC_NOT_FOUND, "No path specified."),
/** Error: 404, "No function found to process the request.". */
NO_XQUERY(SC_NOT_FOUND, "No function found that matches the request."),
/** Error 501, "Method not supported: %.". */
NOT_IMPLEMENTED_X(SC_NOT_IMPLEMENTED, "Method not supported: %.");
/** Status code. */
final int code;
/** Error description. */
final String desc;
/**
* Constructor.
* @param c status code
* @param d description
*/
private HTTPErr(final int c, final String d) {
code = c;
desc = d;
}
/**
* Throws an HTTP exception.
* @param ext extended info
* @return HTTP exception
* @throws HTTPException HTTP exception
*/
public HTTPException thrw(final Object... ext) throws HTTPException {
throw new HTTPException(this, ext);
}
}
basex-7.7.2/basex-api/src/main/java/org/basex/http/HTTPException.java 0000664 0000000 0000000 00000001352 12224530032 0025301 0 ustar 00root root 0000000 0000000 package org.basex.http;
import java.io.*;
import org.basex.util.*;
/**
* HTTP exception. Also thrown to pass on correct status codes.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
public final class HTTPException extends IOException {
/** Status code. */
private final int status;
/**
* Constructs an exception with the specified message and extension.
* @param err error
* @param ext message extension
*/
public HTTPException(final HTTPErr err, final Object... ext) {
//this(err.code, err.desc, ext);
super(Util.info(err.desc, ext));
status = err.code;
}
/**
* Returns the status code.
* @return status code
*/
public int getStatus() {
return status;
}
}
basex-7.7.2/basex-api/src/main/java/org/basex/http/HTTPMethod.java 0000664 0000000 0000000 00000001204 12224530032 0024557 0 ustar 00root root 0000000 0000000 package org.basex.http;
/**
* This enumeration contains the supported HTTP methods.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
public enum HTTPMethod {
/** GET method. */
GET,
/** POST method. */
POST,
/** PUT method. */
PUT,
/** DELETE method. */
DELETE,
/** HEAD method. */
HEAD,
/** OPTIONS method. */
OPTIONS;
/**
* Finds the specified method, or returns {@code null}.
* @param name method name
* @return method
*/
public static HTTPMethod get(final String name) {
for(final HTTPMethod m : values()) if(m.name().equals(name)) return m;
return null;
}
}
basex-7.7.2/basex-api/src/main/java/org/basex/http/HTTPText.java 0000664 0000000 0000000 00000002000 12224530032 0024256 0 ustar 00root root 0000000 0000000 package org.basex.http;
/**
* This class assembles texts which are used in the HTTP classes.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
public interface HTTPText {
/** WWW-Authentication string. */
String WWW_AUTHENTICATE = "WWW-Authenticate";
/** HTTP header: Authorization. */
String AUTHORIZATION = "Authorization";
/** HTTP basic authentication. */
String BASIC = "Basic";
/** Location string. */
String LOCATION = "location";
/** HTTP String. */
String HTTP = "HTTP";
/** WEB-INF directory. */
String WEB_INF = "WEB-INF/";
/** Path to jetty configuration file. */
String JETTYCONF = WEB_INF + "jetty.xml";
/** Path to web configuration file. */
String WEBCONF = WEB_INF + "web.xml";
/** Error: no password. */
String NOPASSWD = "No username/password specified.";
/** Error: unsupported authorization method. */
String WHICHAUTH = "Unsupported Authorization method: %.";
/** Error message. */
String UNEXPECTED = "Unexpected error: %";
}
basex-7.7.2/basex-api/src/main/java/org/basex/http/SessionListener.java 0000664 0000000 0000000 00000001623 12224530032 0025775 0 ustar 00root root 0000000 0000000 package org.basex.http;
import java.util.*;
import javax.servlet.http.*;
/**
* This class bundles context-based information on a single HTTP operation.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
public final class SessionListener implements HttpSessionListener {
/** Sessions. */
private static HashMap sessions;
@Override
public void sessionCreated(final HttpSessionEvent event) {
final HttpSession sess = event.getSession();
sessions().put(sess.getId(), sess);
}
@Override
public void sessionDestroyed(final HttpSessionEvent event) {
sessions().remove(event.getSession().getId());
}
/**
* Initializes the HTTP context.
* @return context;
*/
public static synchronized HashMap sessions() {
if(sessions == null) sessions = new HashMap();
return sessions;
}
}
basex-7.7.2/basex-api/src/main/java/org/basex/http/rest/ 0000775 0000000 0000000 00000000000 12224530032 0022754 5 ustar 00root root 0000000 0000000 basex-7.7.2/basex-api/src/main/java/org/basex/http/rest/RESTCode.java 0000664 0000000 0000000 00000007565 12224530032 0025204 0 ustar 00root root 0000000 0000000 package org.basex.http.rest;
import static org.basex.http.rest.RESTText.*;
import static org.basex.query.func.Function.*;
import java.io.*;
import java.util.*;
import java.util.Map.Entry;
import org.basex.core.*;
import org.basex.core.cmd.*;
import org.basex.core.cmd.Set;
import org.basex.http.*;
import org.basex.io.serial.*;
import org.basex.server.*;
import org.basex.util.*;
/**
* Abstract class for performing REST operations.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
public abstract class RESTCode {
/**
* Performs the REST operation.
* @param http HTTP context
* @throws IOException I/O exception
*/
abstract void run(final HTTPContext http) throws IOException;
/**
* Opens the addressed database.
* @param http HTTP context
* @throws HTTPException REST exception
*/
static void open(final HTTPContext http) throws HTTPException {
final String db = http.db();
if(db == null) return;
try {
http.session().execute(new Open(db));
final String path = http.dbpath();
if(!path.isEmpty()) http.session().execute(new Cs(_DB_OPEN.args(db, path)));
} catch(final IOException ex) {
HTTPErr.NOT_FOUND_X.thrw(ex);
}
}
/**
* Sets the wrapping flag.
* @param val value
* @param http HTTP context
* @throws HTTPException REST exception
*/
static void wrap(final String val, final HTTPContext http) throws HTTPException {
http.wrapping = Util.yes(val);
if(!http.wrapping && !Util.no(val)) {
try {
SerializerProp.error(WRAP, val, Text.YES, Text.NO);
} catch(final SerializerException ex) {
HTTPErr.BAD_REQUEST_X.thrw(ex);
}
}
}
/**
* Checks if any resource with the specified name exists.
* @param http HTTP context
* @return number of documents
* @throws IOException I/O exception
*/
protected static boolean exists(final HTTPContext http) throws IOException {
final LocalQuery q = http.session().query(_DB_EXISTS.args("$d", "$p"));
q.bind("d", http.db());
q.bind("p", http.dbpath());
return q.execute().equals(Text.TRUE);
}
/**
* Checks if the specified path points to a binary resource.
* @param http HTTP context
* @return result of check
* @throws IOException I/O exception
*/
protected static boolean isRaw(final HTTPContext http) throws IOException {
final LocalQuery q = http.session().query(_DB_IS_RAW.args("$d", "$p"));
q.bind("d", http.db());
q.bind("p", http.dbpath());
return q.execute().equals(Text.TRUE);
}
/**
* Returns the content type of a database resource.
* @param http HTTP context
* @return content type
* @throws IOException I/O exception
*/
protected static String contentType(final HTTPContext http) throws IOException {
final LocalQuery q = http.session().query(_DB_CONTENT_TYPE.args("$d", "$p"));
q.bind("d", http.db());
q.bind("p", http.dbpath());
return q.execute();
}
/**
* Parses and sets database options.
* Throws an exception if an option is unknown.
* @param http HTTP context
* @throws IOException I/O exception
*/
static void parseOptions(final HTTPContext http) throws IOException {
for(final Entry param : http.params().entrySet()) {
parseOption(http, param, true);
}
}
/**
* Parses and sets a single database option.
* @param http HTTP context
* @param param current parameter
* @param force force execution
* @return success flag
* @throws IOException I/O exception
*/
static boolean parseOption(final HTTPContext http, final Entry param,
final boolean force) throws IOException {
final String key = param.getKey().toUpperCase(Locale.ENGLISH);
final boolean found = http.context().prop.get(key) != null;
if(found || force) http.session().execute(new Set(key, param.getValue()[0]));
return found;
}
}
basex-7.7.2/basex-api/src/main/java/org/basex/http/rest/RESTCommand.java 0000664 0000000 0000000 00000001736 12224530032 0025702 0 ustar 00root root 0000000 0000000 package org.basex.http.rest;
import java.io.*;
import org.basex.data.*;
import org.basex.http.*;
import org.basex.io.serial.*;
import org.basex.server.*;
/**
* REST-based evaluation of database commands.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
public class RESTCommand extends RESTCode {
/** Query input. */
protected final String input;
/**
* Constructor.
* @param in command to be executed
*/
RESTCommand(final String in) {
input = in;
}
@Override
void run(final HTTPContext http) throws IOException {
// open addressed database
open(http);
// set default content type to raw
final String sprop = SerializerProp.S_METHOD[0] + "=" + DataText.M_TEXT +
',' + http.serialization;
http.initResponse(new SerializerProp(sprop));
// perform command
final LocalSession session = http.session();
session.setOutputStream(http.res.getOutputStream());
session.execute(input);
}
}
basex-7.7.2/basex-api/src/main/java/org/basex/http/rest/RESTDelete.java 0000664 0000000 0000000 00000001536 12224530032 0025524 0 ustar 00root root 0000000 0000000 package org.basex.http.rest;
import static org.basex.util.Token.*;
import java.io.*;
import org.basex.core.cmd.*;
import org.basex.http.*;
import org.basex.server.*;
/**
* REST-based evaluation of DELETE operations.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
public class RESTDelete extends RESTCode {
@Override
void run(final HTTPContext http) throws IOException {
// parse database options
parseOptions(http);
// open addressed database
open(http);
final LocalSession session = http.session();
if(http.depth() == 0) {
HTTPErr.NO_PATH.thrw();
} else if(http.depth() == 1) {
session.execute(new DropDB(http.db()));
} else {
session.execute(new Delete(http.dbpath()));
}
// return command info
http.res.getOutputStream().write(token(session.info()));
}
}
basex-7.7.2/basex-api/src/main/java/org/basex/http/rest/RESTGet.java 0000664 0000000 0000000 00000003777 12224530032 0025052 0 ustar 00root root 0000000 0000000 package org.basex.http.rest;
import static org.basex.http.rest.RESTText.*;
import java.io.*;
import java.util.*;
import java.util.Map.Entry;
import org.basex.http.*;
import org.basex.io.serial.*;
import org.basex.util.*;
/**
* This class processes GET requests sent to the REST server.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
final class RESTGet extends RESTCode {
@Override
void run(final HTTPContext http) throws IOException {
final Map vars = new HashMap();
// handle query parameters
String operation = null;
String input = null;
byte[] item = null;
// parse database options
final TokenBuilder ser = new TokenBuilder();
final SerializerProp sp = new SerializerProp();
for(final Entry param : http.params().entrySet()) {
final String key = param.getKey();
final String[] vals = param.getValue();
final String val = vals[0];
if(Token.eqic(key, COMMAND, QUERY, RUN)) {
if(operation != null || vals.length > 1) HTTPErr.ONEOP.thrw();
operation = key;
input = val;
} else if(key.equalsIgnoreCase(WRAP)) {
// wrapping flag
wrap(val, http);
} else if(key.equalsIgnoreCase(CONTEXT)) {
// context parameter
item = Token.token(val);
} else if(sp.get(key) != null) {
// serialization parameters
for(final String v : vals) ser.add(key).add('=').add(v).add(',');
} else if(!parseOption(http, param, false)) {
// external variables
vars.put(key, new String[] { val });
}
}
http.serialization = ser.toString();
final RESTCode code;
if(operation == null) {
code = new RESTRetrieve(input, vars, item);
} else if(operation.equals(QUERY)) {
code = new RESTQuery(input, vars, item);
} else if(operation.equals(RUN)) {
code = new RESTRun(input, vars, item);
} else {
code = new RESTCommand(input);
}
code.run(http);
}
}
basex-7.7.2/basex-api/src/main/java/org/basex/http/rest/RESTPost.java 0000664 0000000 0000000 00000011222 12224530032 0025240 0 ustar 00root root 0000000 0000000 package org.basex.http.rest;
import static org.basex.http.rest.RESTText.*;
import java.io.*;
import java.util.*;
import javax.xml.parsers.*;
import javax.xml.transform.dom.*;
import org.basex.core.*;
import org.basex.core.cmd.Set;
import org.basex.http.*;
import org.basex.io.*;
import org.basex.io.in.*;
import org.basex.io.serial.*;
import org.basex.query.*;
import org.basex.query.util.*;
import org.basex.query.value.item.*;
import org.basex.query.value.node.*;
import org.basex.util.*;
/**
* REST-based evaluation of POST operations.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
public class RESTPost extends RESTCode {
@Override
void run(final HTTPContext http) throws IOException {
parseOptions(http);
String enc = http.req.getCharacterEncoding();
if(enc == null) enc = Token.UTF8;
// perform queries
final byte[] in = new NewlineInput(http.req.getInputStream()).encoding(enc).content();
validate(in);
final Context ctx = http.context();
DBNode doc;
try {
doc = new DBNode(new IOContent(in), ctx.prop);
} catch(final IOException ex) {
throw HTTPErr.BAD_REQUEST_X.thrw(ex);
}
final SerializerProp sp = new SerializerProp();
QueryProcessor qp;
RESTCode code;
try {
// handle serialization parameters
final TokenBuilder ser = new TokenBuilder();
qp = new QueryProcessor("*/*:parameter", ctx).context(doc);
for(final Item param : qp.value()) {
final String name = value("data(@name)", param, ctx);
final String value = value("data(@value)", param, ctx);
if(sp.get(name) != null) {
ser.add(name).add('=').add(value).add(',');
} else if(name.equals(WRAP)) {
wrap(value, http);
} else {
HTTPErr.UNKNOWN_PARAM_X.thrw(name);
}
}
http.serialization = ser.toString();
// handle database options
qp = new QueryProcessor("*/*:option", ctx).context(doc);
for(final Item it : qp.value()) {
final String name = value("data(@name)", it, ctx);
final String value = value("data(@value)", it, ctx);
http.session().execute(new Set(name, value));
}
// handle variables
final Map vars = new HashMap();
qp = new QueryProcessor("*/*:variable", ctx).context(doc);
for(final Item it : qp.value()) {
final String name = value("data(@name)", it, ctx);
final String value = value("data(@value)", it, ctx);
final String type = value("data(@type)", it, ctx);
vars.put(name, new String[] { value, type });
}
// handle input
byte[] item = null;
qp = new QueryProcessor("*/*:context/node()", ctx).context(doc);
for(final Item it : qp.value()) {
if(item != null) HTTPErr.MULTIPLE_CONTEXT_X.thrw();
// create main memory instance of the specified node
item = DataBuilder.stripNS((ANode) it, Token.token(RESTURI), ctx).
serialize().toArray();
}
// handle request
final String request = value("local-name(*)", doc, ctx);
final String text = value("*/*:text/text()", doc, ctx);
if(request.equals(COMMAND)) {
code = new RESTCommand(text);
} else if(request.equals(RUN)) {
code = new RESTRun(text, vars, item);
} else {
code = new RESTQuery(text, vars, item);
}
code.run(http);
} catch(final QueryException ex) {
HTTPErr.BAD_REQUEST_X.thrw(ex);
}
}
/**
* Returns the atomized item for the specified query.
* @param query query
* @param item context item
* @param ctx database context
* @return atomized item
* @throws QueryException query exception
*/
private static String value(final String query, final Item item, final Context ctx)
throws QueryException {
final QueryProcessor qp = new QueryProcessor(query, ctx).context(item);
final Item it = qp.iter().next();
return it == null ? null : Token.string(it.string(null));
}
/**
* Validates the specified XML input against the POST schema.
* @param input input document
* @throws HTTPException exception
*/
private static void validate(final byte[] input) throws HTTPException {
try {
final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
final DocumentBuilder db = dbf.newDocumentBuilder();
RESTSchema.newValidator().validate(new DOMSource(db.parse(new ArrayInput(input))));
} catch(final Exception ex) {
Util.debug("Error while validating \"" + Token.string(input) + '"');
// validation fails
HTTPErr.BAD_REQUEST_X.thrw(ex);
}
}
}
basex-7.7.2/basex-api/src/main/java/org/basex/http/rest/RESTPut.java 0000664 0000000 0000000 00000003705 12224530032 0025072 0 ustar 00root root 0000000 0000000 package org.basex.http.rest;
import static org.basex.io.MimeTypes.*;
import java.io.*;
import org.basex.core.cmd.*;
import org.basex.http.*;
import org.basex.io.*;
import org.basex.io.in.*;
import org.basex.server.*;
/**
* REST-based evaluation of PUT operations.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
public class RESTPut extends RESTCode {
@Override
void run(final HTTPContext http) throws IOException {
// parse database options
parseOptions(http);
// create new database or update resource
final LocalSession session = http.session();
if(http.depth() == 0) HTTPErr.NO_PATH.thrw();
boolean xml = true;
final InputStream in = http.req.getInputStream();
final String ct = http.contentType();
// choose correct importer
if(APP_JSON.equals(ct)) {
session.execute("set parser json");
} else if(APP_JSONML.equals(ct)) {
session.execute("set parser json");
session.execute("set parseropt jsonml=true");
} else if(TEXT_CSV.equals(ct)) {
session.execute("set parser csv");
} else if(TEXT_HTML.equals(ct)) {
session.execute("set parser html");
} else if(ct != null && MimeTypes.isText(ct)) {
session.execute("set parser text");
} else if(ct != null && !MimeTypes.isXML(ct)) {
xml = false;
}
if(http.depth() == 1) {
// store data as XML or raw file, depending on content type
if(xml) {
session.create(http.db(), in);
} else {
session.create(http.db(), new ArrayInput(""));
session.store(http.db(), in);
}
} else {
open(http);
// store data as XML or raw file, depending on content type
if(xml) {
session.replace(http.dbpath(), in);
} else {
session.execute(new Delete(http.dbpath()));
session.store(http.dbpath(), in);
}
}
// return correct status and command info
throw HTTPErr.CREATED_X.thrw(session.info());
}
}
basex-7.7.2/basex-api/src/main/java/org/basex/http/rest/RESTQuery.java 0000664 0000000 0000000 00000006427 12224530032 0025433 0 ustar 00root root 0000000 0000000 package org.basex.http.rest;
import static org.basex.core.Text.*;
import static org.basex.http.rest.RESTText.*;
import java.io.*;
import java.util.*;
import java.util.Map.Entry;
import org.basex.core.*;
import org.basex.core.cmd.*;
import org.basex.core.cmd.Set;
import org.basex.http.*;
import org.basex.io.in.*;
import org.basex.io.serial.*;
import org.basex.server.*;
import org.basex.util.*;
/**
* REST-based evaluation of XQuery expressions.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
class RESTQuery extends RESTCode {
/** External variables. */
protected final Map variables;
/** Query input. */
protected final String input;
/** Optional context item. */
protected final byte[] item;
/**
* Constructor.
* @param in query to be executed
* @param vars external variables
* @param it context item
*/
RESTQuery(final String in, final Map vars, final byte[] it) {
input = in;
variables = vars;
item = it;
}
@Override
void run(final HTTPContext http) throws IOException {
query(input, http, http.context().mprop.get(MainProp.WEBPATH));
}
/**
* Evaluates the specified query.
* @param in query input
* @param http HTTP context
* @param path set query path
* @throws HTTPException REST exception
* @throws IOException I/O exception
*/
protected void query(final String in, final HTTPContext http, final String path)
throws IOException {
final LocalSession session = http.session();
if(item != null) {
// create main memory instance of the document specified as context node
final boolean mm = session.execute(
new Get(Prop.MAINMEM)).split(COLS)[1].equals(TRUE);
session.execute(new Set(Prop.MAINMEM, true));
session.create(Util.name(RESTQuery.class), new ArrayInput(item));
if(!mm) session.execute(new Set(Prop.MAINMEM, false));
} else {
// open addressed database
open(http);
}
// send serialization options to the server
session.execute(new Set(Prop.SERIALIZER, serial(http)));
session.setOutputStream(http.res.getOutputStream());
// set base path to correctly resolve local references
session.execute(new Set(Prop.QUERYPATH, path));
// create query instance and bind http context
final Query qu = session.query(in);
qu.context(http);
// bind external variables
for(final Entry e : variables.entrySet()) {
final String[] val = e.getValue();
if(val.length == 2) qu.bind(e.getKey(), val[0], val[1]);
if(val.length == 1) qu.bind(e.getKey(), val[0]);
}
// initializes the response with query serialization options
http.initResponse(new SerializerProp(qu.options()));
// run query
qu.execute();
}
/**
* Returns a string representation of the used serialization parameters.
* @param http HTTP context
* @return serialization parameters
*/
static String serial(final HTTPContext http) {
final TokenBuilder ser = new TokenBuilder(http.serialization);
if(http.wrapping) {
if(!ser.isEmpty()) ser.add(',');
ser.addExt(SerializerProp.S_WRAP_PREFIX[0]).add('=').add(REST).add(',');
ser.addExt(SerializerProp.S_WRAP_URI[0]).add('=').add(RESTURI);
}
return ser.toString();
}
}
basex-7.7.2/basex-api/src/main/java/org/basex/http/rest/RESTRetrieve.java 0000664 0000000 0000000 00000006660 12224530032 0026112 0 ustar 00root root 0000000 0000000 package org.basex.http.rest;
import static org.basex.http.rest.RESTText.*;
import static org.basex.util.Token.*;
import java.io.*;
import java.util.*;
import org.basex.core.*;
import org.basex.core.cmd.*;
import org.basex.core.cmd.List;
import org.basex.core.cmd.Set;
import org.basex.http.*;
import org.basex.io.serial.*;
import org.basex.query.value.item.*;
import org.basex.query.value.node.*;
import org.basex.server.*;
import org.basex.util.*;
import org.basex.util.list.*;
/**
* This class retrieves resources.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
final class RESTRetrieve extends RESTQuery {
/**
* Constructor.
* @param in input file to be executed
* @param vars external variables
* @param it context item
*/
RESTRetrieve(final String in, final Map vars, final byte[] it) {
super(in, vars, it);
}
@Override
void run(final HTTPContext http) throws IOException {
// open addressed database
open(http);
final LocalSession session = http.session();
if(http.depth() == 0) {
// list databases
final Table table = new Table(session.execute(new List()));
final SerializerProp sprop = new SerializerProp(http.serialization);
final Serializer ser = Serializer.get(http.res.getOutputStream(), sprop);
http.initResponse(sprop);
final FElem el = new FElem(Q_DATABASES).declareNS();
el.add(RESOURCES, token(table.contents.size()));
list(table, el, Q_DATABASE, 1);
ser.serialize(el);
ser.close();
} else if(!exists(http)) {
// list database resources
final Table table = new Table(session.execute(new List(http.db(), http.dbpath())));
final String serial = http.serialization;
final SerializerProp sprop = new SerializerProp(serial);
final Serializer ser = Serializer.get(http.res.getOutputStream(), sprop);
http.initResponse(sprop);
final FElem el = new FElem(Q_DATABASE).declareNS();
el.add(NAME, http.db());
el.add(RESOURCES, token(table.contents.size()));
list(table, el, Q_RESOURCE, 0);
ser.serialize(el);
ser.close();
} else if(isRaw(http)) {
// retrieve raw file; prefix user parameters with media type
final String ct = SerializerProp.S_MEDIA_TYPE[0] + "=" + contentType(http);
http.initResponse(new SerializerProp(ct + ',' + http.serialization));
session.setOutputStream(http.res.getOutputStream());
session.execute(new Retrieve(http.dbpath()));
} else {
// retrieve xml file
http.initResponse(new SerializerProp(http.serialization));
session.execute(new Set(Prop.SERIALIZER, serial(http)));
session.setOutputStream(http.res.getOutputStream());
session.query(".").execute();
}
}
/**
* Lists the table contents.
* @param table table reference
* @param root root node
* @param header table header
* @param skip number of columns to skip
*/
private static void list(final Table table, final FElem root, final QNm header,
final int skip) {
for(final TokenList l : table.contents) {
final FElem el = new FElem(header);
// don't show last attribute (input path)
for(int i = 1; i < l.size() - skip; i++) {
el.add(new QNm(lc(table.header.get(i))), l.get(i));
}
el.add(l.get(0));
root.add(el);
}
}
}
basex-7.7.2/basex-api/src/main/java/org/basex/http/rest/RESTRun.java 0000664 0000000 0000000 00000002152 12224530032 0025061 0 ustar 00root root 0000000 0000000 package org.basex.http.rest;
import static org.basex.core.Text.*;
import java.io.*;
import java.util.*;
import org.basex.core.*;
import org.basex.http.*;
import org.basex.io.*;
import org.basex.util.*;
/**
* REST-based evaluation of XQuery files.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
public class RESTRun extends RESTQuery {
/**
* Constructor.
* @param in input file to be executed
* @param vars external variables
* @param it context item
*/
RESTRun(final String in, final Map vars, final byte[] it) {
super(in, vars, it);
}
@Override
void run(final HTTPContext http) throws IOException {
// get root directory for files
final IOFile root = new IOFile(http.context().mprop.get(MainProp.WEBPATH));
// check if file is not found, is a folder or points to parent folder
final IOFile io = new IOFile(root, input);
if(!io.exists() || io.isDir() || !io.path().startsWith(root.path()))
HTTPErr.NOT_FOUND_X.thrw(Util.info(RES_NOT_FOUND_X, input));
// perform query
query(io.string(), http, io.path());
}
}
basex-7.7.2/basex-api/src/main/java/org/basex/http/rest/RESTSchema.java 0000664 0000000 0000000 00000006625 12224530032 0025526 0 ustar 00root root 0000000 0000000 package org.basex.http.rest;
import javax.xml.*;
import javax.xml.transform.stream.*;
import javax.xml.validation.*;
import org.basex.io.in.*;
import org.basex.util.*;
import org.xml.sax.*;
/**
* XML Schemas for REST requests.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
enum RESTSchema {
/** Single instance. */
INSTANCE;
/** Validation schema. */
private final Schema schema;
/** Constructor. */
private RESTSchema() {
Schema s = null;
try {
s = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI).
newSchema(new StreamSource(new ArrayInput(Token.token(SCHEMA_CONTENT))));
} catch(final SAXException ex) {
Util.notexpected(ex);
}
schema = s;
}
/**
* Create a new validator against the schema.
* @return a new validator
*/
static Validator newValidator() {
return INSTANCE.schema.newValidator();
}
/** Post Schema. */
private static final String SCHEMA_CONTENT =
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"";
}
basex-7.7.2/basex-api/src/main/java/org/basex/http/rest/RESTServlet.java 0000664 0000000 0000000 00000001666 12224530032 0025752 0 ustar 00root root 0000000 0000000 package org.basex.http.rest;
import org.basex.http.*;
/**
*
This servlet receives and processes REST requests.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
public final class RESTServlet extends BaseXServlet {
@Override
protected void run(final HTTPContext http) throws Exception {
code(http).run(http);
}
/**
* Returns the correct code for the specified HTTP method, or an exception.
* @param http HTTP method
* @return code
* @throws HTTPException HTTP exception
*/
private static RESTCode code(final HTTPContext http) throws HTTPException {
final HTTPMethod mth = http.method;
if(mth == HTTPMethod.GET) return new RESTGet();
if(mth == HTTPMethod.POST) return new RESTPost();
if(mth == HTTPMethod.PUT) return new RESTPut();
if(mth == HTTPMethod.DELETE) return new RESTDelete();
throw HTTPErr.NOT_IMPLEMENTED_X.thrw(http.req.getMethod());
}
}
basex-7.7.2/basex-api/src/main/java/org/basex/http/rest/RESTText.java 0000664 0000000 0000000 00000001672 12224530032 0025247 0 ustar 00root root 0000000 0000000 package org.basex.http.rest;
import org.basex.core.*;
import org.basex.query.value.item.*;
/**
* This class assembles texts which are used in the HTTP classes.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
public interface RESTText {
/** REST string. */
String REST = "rest";
/** REST URI. */
String RESTURI = Text.URL + '/' + REST;
/** Name. */
QNm Q_DATABASES = QNm.get(REST, "databases", RESTURI);
/** Name. */
QNm Q_DATABASE = QNm.get(REST, "databases", RESTURI);
/** Name. */
QNm Q_RESOURCE = QNm.get(REST, "resource", RESTURI);
/** Attribute. */
String RESOURCES = "resources";
/** Attribute. */
String NAME = "name";
/** Command operation. */
String COMMAND = "command";
/** Run operation. */
String RUN = "run";
/** Query operation. */
String QUERY = "query";
/** Wrap parameter. */
String WRAP = "wrap";
/** Initial context. */
String CONTEXT = "context";
}
basex-7.7.2/basex-api/src/main/java/org/basex/http/restxq/ 0000775 0000000 0000000 00000000000 12224530032 0023325 5 ustar 00root root 0000000 0000000 basex-7.7.2/basex-api/src/main/java/org/basex/http/restxq/RestXqError.java 0000664 0000000 0000000 00000001607 12224530032 0026434 0 ustar 00root root 0000000 0000000 package org.basex.http.restxq;
import org.basex.query.value.item.*;
import org.basex.util.*;
/**
* This class contains a RESTXQ error.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
final class RestXqError implements Comparable {
/** Error code ({@code null}: wildcard). */
final QNm code;
/**
* Constructor.
* @param error error code ({@code null}: wildcard)
*/
RestXqError(final QNm error) {
code = error;
}
/**
* Checks if the specified name matches the test.
* @param nm name
* @return result of check
*/
boolean matches(final QNm nm) {
return code == null || code.eq(nm);
}
@Override
public int compareTo(final RestXqError rxe) {
return code == null ? rxe.code == null ? 0 : -1 : 1;
}
@Override
public String toString() {
return code == null ? "*" : Token.string(code.string());
}
}
basex-7.7.2/basex-api/src/main/java/org/basex/http/restxq/RestXqFunction.java 0000664 0000000 0000000 00000045230 12224530032 0027130 0 ustar 00root root 0000000 0000000 package org.basex.http.restxq;
import static org.basex.http.HTTPMethod.*;
import static org.basex.http.restxq.RestXqText.*;
import static org.basex.util.Token.*;
import java.io.*;
import java.net.*;
import java.util.*;
import java.util.regex.*;
import javax.servlet.http.*;
import org.basex.core.*;
import org.basex.http.*;
import org.basex.io.*;
import org.basex.io.in.*;
import org.basex.io.serial.*;
import org.basex.query.*;
import org.basex.query.expr.*;
import org.basex.query.func.*;
import org.basex.query.iter.*;
import org.basex.query.util.*;
import org.basex.query.util.http.*;
import org.basex.query.value.*;
import org.basex.query.value.item.*;
import org.basex.query.value.seq.*;
import org.basex.query.value.type.*;
import org.basex.query.var.*;
import org.basex.util.*;
import org.basex.util.list.*;
/**
* This class represents a single RESTXQ function.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
final class RestXqFunction implements Comparable {
/** Pattern for a single template. */
private static final Pattern TEMPLATE =
Pattern.compile("\\s*\\{\\s*\\$(.+?)\\s*\\}\\s*");
/** Supported methods. */
EnumSet methods = EnumSet.allOf(HTTPMethod.class);
/** Serialization parameters. */
final SerializerProp output;
/** Associated function. */
final StaticFunc function;
/** Associated module. */
final RestXqModule module;
/** Path. */
RestXqPath path;
/** Error. */
RestXqError error;
/** Query parameters. */
final ArrayList errorParams = new ArrayList();
/** Query parameters. */
final ArrayList queryParams = new ArrayList();
/** Form parameters. */
final ArrayList formParams = new ArrayList();
/** Header parameters. */
final ArrayList headerParams = new ArrayList();
/** Cookie parameters. */
final ArrayList cookieParams = new ArrayList();
/** Query context. */
private final QueryContext context;
/** Consumed media types. */
private final StringList consumes = new StringList();
/** Returned media types. */
private final StringList produces = new StringList();
/** Post/Put variable. */
private QNm requestBody;
/**
* Constructor.
* @param uf associated user function
* @param qc query context
* @param m associated module
*/
RestXqFunction(final StaticFunc uf, final QueryContext qc, final RestXqModule m) {
function = uf;
context = qc;
module = m;
output = qc.serParams(false);
}
/**
* Processes the HTTP request.
* Parses new modules and discards obsolete ones.
* @param http HTTP context
* @param exc optional query exception
* @throws Exception exception
*/
void process(final HTTPContext http, final QueryException exc) throws Exception {
try {
module.process(http, this, exc);
} catch(final QueryException ex) {
if(ex.file() == null) ex.info(function.info);
throw ex;
}
}
/**
* Checks a function for RESTFful annotations.
* @return {@code true} if module contains relevant annotations
* @throws QueryException query exception
*/
boolean parse() throws QueryException {
// parse all annotations
final EnumSet mth = EnumSet.noneOf(HTTPMethod.class);
final boolean[] declared = new boolean[function.args.length];
boolean found = false;
final int as = function.ann.size();
for(int a = 0; a < as; a++) {
final QNm name = function.ann.names[a];
final Value value = function.ann.values[a];
final InputInfo info = function.ann.infos[a];
final byte[] local = name.local();
final byte[] uri = name.uri();
final boolean rexq = eq(uri, QueryText.RESTURI);
if(rexq) {
if(eq(PATH, local)) {
// annotation "path"
if(path != null) error(info, ANN_TWICE, "%", name.string());
path = new RestXqPath(toString(value, name));
for(final String s : path) {
if(s.trim().startsWith("{")) checkVariable(s, AtomType.AAT, declared);
}
} else if(eq(ERROR, local)) {
// annotation "error"
if(error != null) error(info, ANN_TWICE, "%", name.string());
error = error(value, name);
} else if(eq(CONSUMES, local)) {
// annotation "consumes"
strings(value, name, consumes);
} else if(eq(PRODUCES, local)) {
// annotation "produces"
strings(value, name, produces);
} else if(eq(QUERY_PARAM, local)) {
// annotation "query-param"
queryParams.add(param(value, name, declared));
} else if(eq(FORM_PARAM, local)) {
// annotation "form-param"
formParams.add(param(value, name, declared));
} else if(eq(HEADER_PARAM, local)) {
// annotation "header-param"
headerParams.add(param(value, name, declared));
} else if(eq(COOKIE_PARAM, local)) {
// annotation "cookie-param"
cookieParams.add(param(value, name, declared));
} else if(eq(ERROR_PARAM, local)) {
// annotation "error-param"
errorParams.add(param(value, name, declared));
} else {
// method annotations
final HTTPMethod m = HTTPMethod.get(string(local));
if(m == null) error(info, ANN_UNKNOWN, "%", name.string());
if(!value.isEmpty()) {
// remember post/put variable
if(requestBody != null) error(info, ANN_TWICE, "%", name.string());
if(m != POST && m != PUT) error(info, METHOD_VALUE, m);
requestBody = checkVariable(toString(value, name), declared);
}
if(mth.contains(m)) error(info, ANN_TWICE, "%", name.string());
mth.add(m);
}
} else if(eq(uri, QueryText.OUTPUTURI)) {
// serialization parameters
final String key = string(local);
final String val = toString(value, name);
if(output.get(key) == null) error(info, UNKNOWN_SER, key);
output.set(key, val);
}
found |= rexq;
}
if(!mth.isEmpty()) methods = mth;
if(found) {
if(path == null && error == null)
error(function.info, ANN_MISSING, '%', PATH, '%', ERROR);
for(int i = 0; i < declared.length; i++) {
if(declared[i]) continue;
error(function.info, VAR_UNDEFINED, function.args[i].name.string());
}
}
return found;
}
/**
* Checks if an HTTP request matches this function and its constraints.
* @param http http context
* @param err error code
* @return result of check
*/
boolean matches(final HTTPContext http, final QNm err) {
// check method, consumed and produced media type, and path or error
return methods.contains(http.method) && consumes(http) && produces(http) &&
(err == null ? path != null && path.matches(http) :
error != null && error.matches(err));
}
/**
* Binds the annotated variables.
* @param http http context
* @param arg argument array
* @param err optional query error
* @throws QueryException query exception
* @throws IOException I/O exception
*/
void bind(final HTTPContext http, final Expr[] arg, final QueryException err)
throws QueryException, IOException {
// bind variables from segments
if(path != null) {
for(int s = 0; s < path.size; s++) {
final Matcher m = TEMPLATE.matcher(path.segment[s]);
if(!m.find()) continue;
final QNm qnm = new QNm(token(m.group(1)), context);
bind(qnm, arg, new Atm(http.segment(s)));
}
}
// cache request body
final String ct = http.contentType();
IOContent body = null;
if(requestBody != null) {
// bind request body in the correct format
body = cache(http, null);
try {
final String ext = http.contentTypeExt();
bind(requestBody, arg, HTTPPayload.value(body, context.context.prop, ct, ext));
} catch(final IOException ex) {
error(INPUT_CONV, ex);
}
}
// convert parameters to XQuery values
final Map params = new HashMap();
for(final Map.Entry entry : http.params().entrySet()) {
final String[] values = entry.getValue();
final ValueBuilder vb = new ValueBuilder(values.length);
for(final String v : values) vb.add(new Atm(v));
params.put(entry.getKey(), vb.value());
}
// bind query parameters
for(final RestXqParam rxp : queryParams) bind(rxp, arg, params.get(rxp.key));
// bind form parameters
if(!formParams.isEmpty()) {
if(MimeTypes.MULTIPART_FORM_DATA.equals(ct)) {
// convert multipart parameters encoded in a form
addMultipart(cache(http, body), params, http.contentTypeExt());
} else if(MimeTypes.APP_FORM_URLENCODED.equals(ct)) {
// convert URL-encoded parameters
addURLEncoded(cache(http, body), params);
}
for(final RestXqParam rxp : formParams) bind(rxp, arg, params.get(rxp.key));
}
// bind header parameters
for(final RestXqParam rxp : headerParams) {
final TokenList tl = new TokenList();
final Enumeration> en = http.req.getHeaders(rxp.key);
while(en.hasMoreElements()) {
for(final String s : en.nextElement().toString().split(", *")) tl.add(s);
}
bind(rxp, arg, StrSeq.get(tl));
}
// bind cookie parameters
final Cookie[] ck = http.req.getCookies();
for(final RestXqParam rxp : cookieParams) {
Value val = Empty.SEQ;
if(ck != null) {
for(final Cookie c : ck) {
if(rxp.key.equals(c.getName())) val = Str.get(c.getValue());
}
}
bind(rxp, arg, val);
}
// bind errors
final Map errs = new HashMap();
if(err != null) {
final Value[] values = Catch.values(err);
for(int v = 0; v < Catch.NAMES.length; v++) {
errs.put(string(Catch.NAMES[v].local()), values[v]);
}
}
for(final RestXqParam rxp : errorParams) bind(rxp, arg, errs.get(rxp.key));
}
/**
* Creates an exception with the specified message.
* @param msg message
* @param ext error extension
* @return exception
* @throws QueryException query exception
*/
QueryException error(final String msg, final Object... ext) throws QueryException {
throw error(function.info, msg, ext);
}
/**
* Creates an exception with the specified message.
* @param info input info
* @param msg message
* @param ext error extension
* @return exception
* @throws QueryException query exception
*/
QueryException error(final InputInfo info, final String msg, final Object... ext)
throws QueryException {
throw new QueryException(info, Err.BASX_RESTXQ, Util.info(msg, ext));
}
@Override
public int compareTo(final RestXqFunction rxf) {
return path == null ? error.compareTo(rxf.error) : path.compareTo(rxf.path);
}
// PRIVATE METHODS ====================================================================
/**
* Checks the specified template and adds a variable.
* @param tmp template string
* @param declared variable declaration flags
* @return resulting variable
* @throws QueryException query exception
*/
private QNm checkVariable(final String tmp, final boolean[] declared)
throws QueryException {
return checkVariable(tmp, AtomType.ITEM, declared);
}
/**
* Checks the specified template and adds a variable.
* @param tmp template string
* @param type allowed type
* @param declared variable declaration flags
* @return resulting variable
* @throws QueryException query exception
*/
private QNm checkVariable(final String tmp, final Type type, final boolean[] declared)
throws QueryException {
final Var[] args = function.args;
final Matcher m = TEMPLATE.matcher(tmp);
if(!m.find()) error(INV_TEMPLATE, tmp);
final byte[] vn = token(m.group(1));
if(!XMLToken.isQName(vn)) error(INV_VARNAME, vn);
final QNm name = new QNm(vn);
if(name.hasPrefix()) name.uri(context.sc.ns.uri(name.prefix()));
int r = -1;
while(++r < args.length && !args[r].name.eq(name));
if(r == args.length) error(UNKNOWN_VAR, vn);
if(declared[r]) error(VAR_ASSIGNED, vn);
final SeqType st = args[r].declaredType();
if(args[r].checksType() && !st.type.instanceOf(type)) error(INV_VARTYPE, vn, type);
declared[r] = true;
return name;
}
/**
* Checks if the consumed content type matches.
* @param http http context
* @return result of check
*/
private boolean consumes(final HTTPContext http) {
// return true if no type is given
if(consumes.isEmpty()) return true;
// return true if no content type is specified by the user
final String ct = http.contentType();
if(ct == null) return true;
// check if any combination matches
for(final String c : consumes) {
if(MimeTypes.matches(c, ct)) return true;
}
return false;
}
/**
* Checks if the produced content type matches.
* @param http http context
* @return result of check
*/
private boolean produces(final HTTPContext http) {
// return true if no type is given
if(produces.isEmpty()) return true;
// check if any combination matches
for(final String pr : http.produces()) {
for(final String p : produces) {
if(MimeTypes.matches(p, pr)) return true;
}
}
return false;
}
/**
* Binds the specified parameter to a variable.
* @param rxp parameter
* @param args argument array
* @param value values to be bound; the parameter's default value is assigned
* if the argument is {@code null} or empty
* @throws QueryException query exception
*/
private void bind(final RestXqParam rxp, final Expr[] args, final Value value)
throws QueryException {
bind(rxp.name, args, value == null || value.isEmpty() ? rxp.value : value);
}
/**
* Binds the specified value to a variable.
* @param name variable name
* @param args argument array
* @param value value to be bound
* @throws QueryException query exception
*/
private void bind(final QNm name, final Expr[] args, final Value value)
throws QueryException {
// skip nulled values
if(value == null) return;
for(int i = 0; i < function.args.length; i++) {
final Var var = function.args[i];
if(!var.name.eq(name)) continue;
// casts and binds the value
final SeqType decl = var.declaredType();
final Value val = value.type().instanceOf(decl) ? value :
decl.cast(value, context, null, var);
args[i] = var.checkType(val, context, null);
break;
}
}
/**
* Returns the specified value as an atomic string.
* @param value value
* @param name name
* @return string
* @throws QueryException HTTP exception
*/
private String toString(final Value value, final QNm name) throws QueryException {
if(!(value instanceof Str))
error(function.info, ANN_STRING, "%", name.string(), value);
return ((Str) value).toJava();
}
/**
* Adds items to the specified list.
* @param value value
* @param name name
* @param list list to add values to
* @throws QueryException HTTP exception
*/
private void strings(final Value value, final QNm name, final StringList list)
throws QueryException {
final long vs = value.size();
for(int v = 0; v < vs; v++) list.add(toString(value.itemAt(v), name));
}
/**
* Returns a parameter.
* @param value value
* @param name name
* @param declared variable declaration flags
* @return parameter
* @throws QueryException HTTP exception
*/
private RestXqParam param(final Value value, final QNm name, final boolean[] declared)
throws QueryException {
final long vs = value.size();
if(vs < 2) error(function.info, ANN_ATLEAST, "%", name.string(), 2);
// name of parameter
final String key = toString(value.itemAt(0), name);
// variable template
final QNm qnm = checkVariable(toString(value.itemAt(1), name), declared);
// default value
final ValueBuilder vb = new ValueBuilder();
for(int v = 2; v < vs; v++) vb.add(value.itemAt(v));
return new RestXqParam(qnm, key, vb.value());
}
/**
* Returns an error.
* @param value value
* @param name name
* @return parameter
* @throws QueryException HTTP exception
*/
private RestXqError error(final Value value, final QNm name) throws QueryException {
if(value.size() != 1) error(function.info, ANN_EXACTLY, "%", name.string(), 1);
// name of parameter
final String err = toString(value.itemAt(0), name);
QNm code = null;
if(!err.equals("*")) {
final byte[] c = token(err);
if(!XMLToken.isQName(c)) error(INV_CODE, c);
code = new QNm(c, context);
if(!code.hasURI() && code.hasPrefix()) error(INV_NONS, code);
}
// message
return new RestXqError(code);
}
/**
* Adds multipart form-data from the passed on request body.
* @param body request body
* @param pars map parameters
* @param ext content type extension (may be {@code null})
* @throws IOException I/O exception
* @throws QueryException query exception
*/
private void addMultipart(final IOContent body, final Map pars,
final String ext) throws IOException, QueryException {
final Prop prop = context.context.prop;
final HTTPPayload hp = new HTTPPayload(body.inputStream(), false, null, prop);
final HashMap map = hp.multiForm(ext);
for(final Map.Entry entry : map.entrySet()) {
pars.put(entry.getKey(), entry.getValue());
}
}
// PRIVATE STATIC METHODS =============================================================
/**
* Caches the request body, if not done yet.
* @param http http context
* @param cache cache existing cache reference
* @return cache
* @throws IOException I/O exception
*/
private static IOContent cache(final HTTPContext http, final IOContent cache)
throws IOException {
if(cache != null) return cache;
final BufferInput bi = new BufferInput(http.req.getInputStream());
final IOContent io = new IOContent(bi.content());
io.name(http.method + IO.XMLSUFFIX);
return io;
}
/**
* Adds URL-encoded parameters from the passed on request body.
* @param body request body
* @param pars map parameters
*/
private static void addURLEncoded(final IOContent body,
final Map pars) {
for(final String nv : body.toString().split("&")) {
final String[] parts = nv.split("=", 2);
if(parts.length < 2) continue;
try {
pars.put(parts[0], Str.get(URLDecoder.decode(parts[1], Token.UTF8)));
} catch(final Exception ex) {
Util.notexpected(ex);
}
}
}
}
basex-7.7.2/basex-api/src/main/java/org/basex/http/restxq/RestXqModule.java 0000664 0000000 0000000 00000007010 12224530032 0026562 0 ustar 00root root 0000000 0000000 package org.basex.http.restxq;
import static org.basex.query.util.Err.*;
import static org.basex.util.Token.*;
import java.io.*;
import java.util.*;
import org.basex.http.*;
import org.basex.io.*;
import org.basex.query.*;
import org.basex.query.func.*;
/**
* This class caches information on a single XQuery module with RESTXQ annotations.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
final class RestXqModule {
/** Supported methods. */
private final ArrayList functions = new ArrayList();
/** File reference. */
private final IOFile file;
/** Main module flag. */
private final boolean main;
/** Parsing timestamp. */
private long time;
/**
* Constructor.
* @param in xquery module
* @param m main module flag
*/
RestXqModule(final IOFile in, final boolean m) {
file = in;
time = in.timeStamp();
main = m;
}
/**
* Checks the module for RESTXQ annotations.
* @param http http context
* @return {@code true} if module contains relevant annotations
* @throws QueryException query exception
*/
boolean parse(final HTTPContext http) throws QueryException {
functions.clear();
// loop through all functions
final QueryContext qc = parseModule(http);
try {
// loop through all functions
for(final StaticFunc uf : qc.funcs.funcs()) {
// consider only functions that are defined in this module
if(!file.name().equals(new IOFile(uf.info.file()).name())) continue;
final RestXqFunction rxf = new RestXqFunction(uf, qc, this);
if(rxf.parse()) functions.add(rxf);
}
} finally {
qc.close();
}
return !functions.isEmpty();
}
/**
* Checks if the timestamp is still up-to-date.
* @return result of check
*/
boolean uptodate() {
return time == file.timeStamp();
}
/**
* Updates the timestamp.
*/
void touch() {
time = file.timeStamp();
}
/**
* Returns all functions.
* @return functions
*/
ArrayList functions() {
return functions;
}
/**
* Processes the HTTP request.
* @param http HTTP context
* @param func function to be processed
* @param error optional error reference
* @throws Exception exception
*/
void process(final HTTPContext http, final RestXqFunction func,
final QueryException error) throws Exception {
// create new XQuery instance
final QueryContext qc = parseModule(http);
try {
// loop through all functions
for(final StaticFunc uf : qc.funcs.funcs()) {
// compare input info
if(!func.function.info.equals(uf.info)) continue;
final RestXqFunction rxf = new RestXqFunction(uf, qc, this);
rxf.parse();
new RestXqResponse(rxf, qc, http, error).create();
break;
}
} finally {
qc.close();
}
}
// PRIVATE METHODS ====================================================================
/**
* Parses the module and returns the query context.
* @param http http context
* @return query context
* @throws QueryException query exception
*/
private QueryContext parseModule(final HTTPContext http) throws QueryException {
final QueryContext qc = new QueryContext(http.context());
try {
final String cont = string(file.read());
final String path = file.path();
if(main) qc.parseMain(cont, path);
else qc.parseLibrary(cont, path);
return qc;
} catch(final IOException ex) {
throw IOERR.thrw(null, ex);
}
}
}
basex-7.7.2/basex-api/src/main/java/org/basex/http/restxq/RestXqModules.java 0000664 0000000 0000000 00000011012 12224530032 0026742 0 ustar 00root root 0000000 0000000 package org.basex.http.restxq;
import static org.basex.http.restxq.RestXqText.*;
import java.io.*;
import java.util.*;
import org.basex.core.*;
import org.basex.http.*;
import org.basex.io.*;
import org.basex.query.*;
import org.basex.query.value.item.*;
import org.basex.query.value.node.*;
import org.basex.util.*;
/**
* This class caches RESTXQ modules found in the HTTP root directory.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
public final class RestXqModules {
/** Class instance. */
private static final RestXqModules INSTANCE = new RestXqModules();
/** Module cache. */
private HashMap modules = new HashMap();
/** RESTXQ path. */
private IOFile restxq;
/** Private constructor. */
private RestXqModules() { }
/**
* Returns the singleton instance.
* @return instance
*/
public static RestXqModules get() {
return INSTANCE;
}
/**
* Returns a WADL description for all available URIs.
* @param http HTTP context
* @return WADL description
*/
public FElem wadl(final HTTPContext http) {
return new RestXqWadl(http).create(modules);
}
/**
* Returns the function that matches the current request or the specified error code.
* Returns {@code null} if no function matches.
* @param http HTTP context
* @param error error code (optional)
* @throws QueryException query exception
* @return function
*/
RestXqFunction find(final HTTPContext http, final QNm error) throws QueryException {
cache(http);
// collect all functions
final ArrayList list = new ArrayList();
for(final RestXqModule mod : modules.values()) {
for(final RestXqFunction rxf : mod.functions()) {
if(rxf.matches(http, error)) list.add(rxf);
}
}
// no path matches
if(list.isEmpty()) return null;
// choose most appropriate function
RestXqFunction first = list.get(0);
if(list.size() > 1) {
// sort by specifity
Collections.sort(list);
first = list.get(0);
// disallow more than one path with the same specifity
if(first.compareTo(list.get(1)) == 0) {
final TokenBuilder tb = new TokenBuilder();
for(final RestXqFunction rxf : list) {
if(first.compareTo(rxf) != 0) break;
tb.add(Prop.NL).add(rxf.function.info.toString());
}
if(first.path != null) first.error(PATH_CONFLICT, first.path, tb);
first.error(ERROR_CONFLICT, first.error, tb);
}
}
// choose most specific function
return first;
}
/**
* Updates the module cache. Parses new modules and discards obsolete ones.
* @param http http context
* @throws QueryException query exception
*/
private synchronized void cache(final HTTPContext http) throws QueryException {
// initialize RESTXQ directory (may be relative against WEBPATH)
if(restxq == null) {
final File fl = new File(http.context().mprop.get(MainProp.RESTXQPATH));
restxq = fl.isAbsolute() ? new IOFile(fl) :
new IOFile(http.context().mprop.get(MainProp.WEBPATH), fl.getPath());
}
// create new cache
final HashMap cache = new HashMap();
cache(http, restxq, cache);
modules = cache;
}
/**
* Parses the specified path for RESTXQ modules and caches new entries.
* @param root root path
* @param http http context
* @param cache cached modules
* @throws QueryException query exception
*/
private synchronized void cache(final HTTPContext http, final IOFile root,
final HashMap cache) throws QueryException {
for(final IOFile file : root.children()) {
if(file.isDir()) {
cache(http, file, cache);
} else {
final String path = file.path();
final boolean main = path.endsWith(IO.XQSUFFIX);
if(main || path.endsWith(IO.XQMSUFFIX)) {
// all files with .xqm suffix will be parsed for RESTXQ annotations
RestXqModule module = modules.get(path);
boolean parsed = false;
if(module != null) {
// check if module has been modified
parsed = module.uptodate();
} else {
// create new module
module = new RestXqModule(file, main);
}
// add module if it has been parsed, and if it contains annotations
if(parsed || module.parse(http)) {
module.touch();
cache.put(path, module);
}
}
}
}
}
}
basex-7.7.2/basex-api/src/main/java/org/basex/http/restxq/RestXqParam.java 0000664 0000000 0000000 00000001202 12224530032 0026372 0 ustar 00root root 0000000 0000000 package org.basex.http.restxq;
import org.basex.query.value.*;
import org.basex.query.value.item.*;
/**
* This class contains a single RESTXQ parameter.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
final class RestXqParam {
/** Variable name. */
final QNm name;
/** Name of parameter. */
final String key;
/** Default value. */
final Value value;
/**
* Constructor.
* @param nm variable name
* @param param name of parameter
* @param def default value
*/
RestXqParam(final QNm nm, final String param, final Value def) {
name = nm;
key = param;
value = def;
}
}
basex-7.7.2/basex-api/src/main/java/org/basex/http/restxq/RestXqPath.java 0000664 0000000 0000000 00000004216 12224530032 0026236 0 ustar 00root root 0000000 0000000 package org.basex.http.restxq;
import java.util.*;
import org.basex.http.*;
import org.basex.util.*;
/**
* This class represents the path of a RESTXQ function.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
final class RestXqPath implements Iterable, Comparable {
/** Path segments. */
final String[] segment;
/** Number of segments. */
final int size;
/**
* Constructor.
* @param path path
*/
RestXqPath(final String path) {
segment = HTTPContext.toSegments(path);
size = segment.length;
}
/**
* Checks if the path matches the HTTP request.
* @param http http context
* @return result of check
*/
boolean matches(final HTTPContext http) {
// check if number of segments match
if(size != http.depth()) return false;
// check single segments
for(int s = 0; s < size; s++) {
if(!segment[s].equals(http.segment(s)) && !isTemplate(s)) return false;
}
return true;
}
/**
* Checks if the specified path segment is a template.
* @param s offset of segment
* @return result of check
*/
private boolean isTemplate(final int s) {
return segment[s].trim().startsWith("{");
}
@Override
public int compareTo(final RestXqPath rxs) {
final int d = size - rxs.size;
if(d != 0) return d;
for(int s = 0; s < size; s++) {
final boolean wc1 = isTemplate(s);
final boolean wc2 = rxs.isTemplate(s);
if(wc1 != wc2) return wc1 ? 1 : -1;
}
return 0;
}
@Override
public Iterator iterator() {
return new Iterator() {
private int c;
@Override
public boolean hasNext() { return c < size; }
@Override
public String next() { return segment[c++]; }
@Override
public void remove() { Util.notexpected(); }
};
}
@Override
public String toString() {
// returns a schematic representation of the segments
final StringBuilder sb = new StringBuilder("/");
for(int s = 0; s < size; s++) {
sb.append(segment[s]).append('/');
//sb.append(isTemplate(s) ? "{...}" : segment[s]).append('/');
}
return sb.toString();
}
}
basex-7.7.2/basex-api/src/main/java/org/basex/http/restxq/RestXqRespBuilder.java 0000664 0000000 0000000 00000006646 12224530032 0027573 0 ustar 00root root 0000000 0000000 package org.basex.http.restxq;
import static org.basex.http.restxq.RestXqText.*;
import static org.basex.util.Token.*;
import org.basex.http.*;
import org.basex.io.*;
import org.basex.io.out.*;
import org.basex.io.serial.*;
import org.basex.query.func.*;
import org.basex.query.iter.*;
import org.basex.query.value.item.*;
import org.basex.query.value.node.*;
import org.basex.util.hash.*;
/**
* This class holds information on a custom RESTXQ response.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
final class RestXqRespBuilder {
/** Output cache. */
final ArrayOutput cache = new ArrayOutput();;
/** Show error. */
boolean error;
/** Status code. */
int status;
/** Status message. */
String message;
/**
* Builds a response element and creates the serialization parameters.
* @param response response element
* @param func function
* @param iter result iterator
* @param http http context
* @throws Exception exception (including unexpected ones)
*/
void build(final ANode response, final RestXqFunction func,
final Iter iter, final HTTPContext http) throws Exception {
// don't allow attributes
for(final ANode a : response.attributes()) func.error(UNEXP_NODE, a);
// parse response and serialization parameters
SerializerProp sp = func.output;
String cType = null;
for(final ANode n : response.children()) {
// process http:response element
if(HTTP_RESPONSE.eq(n)) {
// check status and reason
byte[] sta = null, msg = null;
for(final ANode a : n.attributes()) {
final QNm qnm = a.qname();
if(qnm.eq(Q_STATUS)) sta = a.string();
else if(qnm.eq(Q_REASON) || qnm.eq(Q_MESSAGE)) msg = a.string();
else func.error(UNEXP_NODE, a);
}
if(sta != null) {
status = toInt(sta);
message = msg != null ? string(msg) : null;
}
for(final ANode c : n.children()) {
// process http:header elements
if(HTTP_HEADER.eq(c)) {
final byte[] nam = c.attribute(Q_NAME);
final byte[] val = c.attribute(Q_VALUE);
if(nam != null && val != null) {
final String key = string(nam);
final String value = string(val);
if(key.equals(MimeTypes.CONTENT_TYPE)) {
cType = value;
} else {
http.res.setHeader(key, value);
}
}
} else {
func.error(UNEXP_NODE, c);
}
}
} else if(OUTPUT_SERIAL.eq(n)) {
// parse output:serialization-parameters
sp = FuncParams.serializerProp(n, func.function.info);
// loop through single values
final TokenMap tm = FuncParams.serializerMap(n, func.function.info);
for(final byte[] key : tm) func.output.set(string(key), string(tm.get(key)));
} else {
func.error(UNEXP_NODE, n);
}
}
// set content type
if(cType != null) sp.set(SerializerProp.S_MEDIA_TYPE, cType);
// check next item
Item item = iter.next();
if(item == null) {
error = true;
} else if(func.methods.size() == 1 && func.methods.contains(HTTPMethod.HEAD)) {
func.error(HEAD_METHOD);
}
// cache result
http.initResponse(sp);
final Serializer ser = Serializer.get(cache, sp);
for(; item != null; item = iter.next()) ser.serialize(item);
ser.close();
}
}
basex-7.7.2/basex-api/src/main/java/org/basex/http/restxq/RestXqResponse.java 0000664 0000000 0000000 00000007465 12224530032 0027151 0 ustar 00root root 0000000 0000000 package org.basex.http.restxq;
import static org.basex.http.restxq.RestXqText.*;
import static org.basex.util.Token.*;
import org.basex.http.*;
import org.basex.io.serial.*;
import org.basex.query.*;
import org.basex.query.expr.*;
import org.basex.query.func.*;
import org.basex.query.iter.*;
import org.basex.query.value.item.*;
import org.basex.query.value.node.*;
import org.basex.query.value.type.*;
import org.basex.query.var.*;
/**
* This class creates a new HTTP response.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
final class RestXqResponse {
/** Function to be evaluated. */
private final RestXqFunction function;
/** Query context. */
private final QueryContext query;
/** HTTP context. */
private final HTTPContext http;
/** Optional query error. */
private final QueryException error;
/**
* Constructor.
* @param rxf function to be evaluated
* @param ctx query context
* @param hc HTTP context
* @param err optional query error
*/
RestXqResponse(final RestXqFunction rxf, final QueryContext ctx, final HTTPContext hc,
final QueryException err) {
function = rxf;
query = ctx;
http = hc;
error = err;
}
/**
* Evaluates the specified function and creates a response.
* @throws Exception exception (including unexpected ones)
*/
void create() throws Exception {
String redirect = null, forward = null;
RestXqRespBuilder resp = null;
// bind variables
final StaticFunc uf = function.function;
final Expr[] args = new Expr[uf.args.length];
function.bind(http, args, error);
// wrap function with a function call
final StaticFuncCall sfc = new StaticFuncCall(uf.name, args, uf.sc, uf.info).init(uf);
final MainModule mm = new MainModule(sfc, new VarScope(), null);
// assign main module and http context and register process
query.mainModule(mm);
query.context(http, null);
query.context.register(query);
try {
// compile and evaluate query
query.compile();
final Iter iter = query.iter();
Item item = iter.next();
// handle response element
if(item != null && item.type.isNode()) {
final ANode node = (ANode) item;
// send redirect to browser
if(REST_REDIRECT.eq(node)) {
final ANode ch = node.children().next();
if(ch == null || ch.type != NodeType.TXT) function.error(NO_VALUE, node.name());
redirect = string(ch.string()).trim();
return;
}
// server-side forwarding
if(REST_FORWARD.eq(node)) {
final ANode ch = node.children().next();
if(ch == null || ch.type != NodeType.TXT) function.error(NO_VALUE, node.name());
forward = string(ch.string()).trim();
return;
}
if(REST_RESPONSE.eq(node)) {
resp = new RestXqRespBuilder();
resp.build(node, function, iter, http);
return;
}
}
// HEAD method must return a single response element
if(function.methods.size() == 1 && function.methods.contains(HTTPMethod.HEAD))
function.error(HEAD_METHOD);
// serialize result
final SerializerProp sp = function.output;
http.initResponse(sp);
final Serializer ser = Serializer.get(http.res.getOutputStream(), sp);
for(; item != null; item = iter.next()) ser.serialize(item);
ser.close();
} finally {
query.close();
query.context.unregister(query);
if(redirect != null) {
http.res.sendRedirect(redirect);
} else if(forward != null) {
http.req.getRequestDispatcher(forward).forward(http.req, http.res);
} else if(resp != null) {
if(resp.status != 0) http.status(resp.status, resp.message, resp.error);
http.res.getOutputStream().write(resp.cache.toArray());
}
}
}
}
basex-7.7.2/basex-api/src/main/java/org/basex/http/restxq/RestXqServlet.java 0000664 0000000 0000000 00000002361 12224530032 0026765 0 ustar 00root root 0000000 0000000 package org.basex.http.restxq;
import org.basex.http.*;
import org.basex.query.*;
/**
*
This servlet receives and processes REST requests.
* The evaluated code is defined in XQuery modules, which are located in the web server's
* root directory (specified by the {@code HTTPPATH} option), and decorated with RESTXQ
* annotations.
*
*
The implementation is based on Adam Retter's paper presented at XMLPrague 2012,
* titled "RESTful XQuery - Standardised XQuery 3.0 Annotations for REST".
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
public final class RestXqServlet extends BaseXServlet {
@Override
protected void run(final HTTPContext http) throws Exception {
// authenticate user
http.session();
// analyze input path
final RestXqModules rxm = RestXqModules.get();
// select XQuery function
RestXqFunction func = rxm.find(http, null);
if(func == null) HTTPErr.NO_XQUERY.thrw();
try {
// process function that matches the current request
func.process(http, null);
} catch(final QueryException ex) {
// process optional error function
func = rxm.find(http, ex.qname());
if(func == null) throw ex;
func.process(http, ex);
}
}
}
basex-7.7.2/basex-api/src/main/java/org/basex/http/restxq/RestXqText.java 0000664 0000000 0000000 00000010660 12224530032 0026266 0 ustar 00root root 0000000 0000000 package org.basex.http.restxq;
import static org.basex.query.QueryText.*;
import static org.basex.util.Token.*;
import org.basex.query.func.*;
import org.basex.query.path.*;
import org.basex.query.value.item.*;
/**
* This class assembles texts which are used in the HTTP classes.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
public interface RestXqText {
/** Token "error". */
byte[] ERROR = token("error");
/** Token "path". */
byte[] PATH = token("path");
/** Token "produces". */
byte[] PRODUCES = token("produces");
/** Token "consumes". */
byte[] CONSUMES = token("consumes");
/** Token "query-param". */
byte[] QUERY_PARAM = token("query-param");
/** Token "form-param". */
byte[] FORM_PARAM = token("form-param");
/** Token "header-param". */
byte[] HEADER_PARAM = token("header-param");
/** Token "cookie-param". */
byte[] COOKIE_PARAM = token("cookie-param");
/** Token "query-param". */
byte[] ERROR_PARAM = token("error-param");
/** Token "header". */
byte[] HEADER = token("header");
/** Token "response". */
byte[] RESPONSE = token("response");
/** Token "status". */
byte[] STATUS = token("status");
/** Token "reason". */
byte[] REASON = token("reason");
/** Token "message". */
byte[] MESSAGE = token("message");
/** Token "name". */
byte[] NAME = token("name");
/** Token "value". */
byte[] VALUE = token("value");
/** Token "redirect". */
byte[] REDIRECT = token("redirect");
/** Token "forward". */
byte[] FORWARD = token("forward");
/** WADL prefix. */
String WADL = "wadl:";
/** WADL namespace. */
String WADL_URI = "http://wadl.dev.java.net/2009/02";
/** XHTML namespace. */
String XHTML_URL = "http://www.w3.org/1999/xhtml";
/** Error message. */
String ANN_MISSING = "Annotation %% or %% missing.";
/** Error message. */
String ANN_TWICE = "Annotation %% is specified more than once.";
/** Error message. */
String ANN_UNKNOWN = "Annotation %% is invalid or not supported.";
/** Error message. */
String ANN_ATLEAST = "Annotation %% requires at least % parameter(s).";
/** Error message. */
String ANN_EXACTLY = "Annotation %% requires exactly % parameter(s).";
/** Error message. */
String ANN_STRING = "Single string expected for %%, found: %.";
/** Error message. */
String INV_TEMPLATE = "Invalid path template: \"%\".";
/** Error message. */
String INV_VARNAME = "Invalid variable name: $%.";
/** Error message. */
String INV_CODE = "Invalid error code: '%'.";
/** Error message. */
String INV_NONS = "No namespace declared for '%'.";
/** Error message. */
String INV_VARTYPE = "Variable $% must inherit from %.";
/** Error message. */
String UNKNOWN_VAR = "Variable $% is not specified as argument.";
/** Error message. */
String VAR_ASSIGNED = "Variable $% is specified more than once.";
/** Error message. */
String VAR_UNDEFINED = "Variable $% is not assigned by the annotations.";
/** Error message. */
String UNKNOWN_SER = "Unknown serialization parameter \"%\".";
/** Error message. */
String UNEXP_NODE = "Unexpected node: %.";
/** Error message. */
String HEAD_METHOD = "HEAD method must return a single 'restxq:response' element.";
/** Error message. */
String METHOD_VALUE = "Method % does not allow values.";
/** Error message. */
String INPUT_CONV = "Input could not be converted: %";
/** Error message. */
String PATH_CONFLICT = "Several functions assigned to path \"%\":%";
/** Error message. */
String ERROR_CONFLICT = "Several functions assigned to error \"%\":%";
/** Error message. */
String NO_VALUE = "'%' element has no string value.";
/** QName. */
QNm Q_STATUS = QNm.get(STATUS);
/** QName. */
QNm Q_REASON = QNm.get(REASON);
/** QName. */
QNm Q_MESSAGE = QNm.get(MESSAGE);
/** QName. */
QNm Q_NAME = QNm.get(NAME);
/** QName. */
QNm Q_VALUE = QNm.get(VALUE);
/** Serializer node test. */
NodeTest OUTPUT_SERIAL = new NodeTest(FuncParams.Q_SPARAM);
/** HTTP Response test. */
NodeTest HTTP_RESPONSE = new NodeTest(QNm.get(RESPONSE, HTTPURI));
/** RESTXQ Response test. */
NodeTest REST_RESPONSE = new NodeTest(QNm.get(RESPONSE, RESTURI));
/** RESTXQ Redirect test. */
NodeTest REST_REDIRECT = new NodeTest(QNm.get(REDIRECT, RESTURI));
/** RESTXQ Forward test. */
NodeTest REST_FORWARD = new NodeTest(QNm.get(FORWARD, RESTURI));
/** HTTP Header test. */
NodeTest HTTP_HEADER = new NodeTest(QNm.get(HEADER, HTTPURI));
}
basex-7.7.2/basex-api/src/main/java/org/basex/http/restxq/RestXqWadl.java 0000664 0000000 0000000 00000011030 12224530032 0026221 0 ustar 00root root 0000000 0000000 package org.basex.http.restxq;
import static org.basex.http.restxq.RestXqText.*;
import static org.basex.query.QueryText.*;
import static org.basex.util.Token.*;
import java.util.*;
import java.util.regex.*;
import org.basex.http.*;
import org.basex.query.util.inspect.*;
import org.basex.query.value.item.*;
import org.basex.query.value.node.*;
import org.basex.query.var.*;
import org.basex.util.hash.*;
import org.basex.util.list.*;
/**
* This class returns a Web Application Description Language (WADL) file,
* listing all available RESTXQ services.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
final class RestXqWadl {
/** HTTP context. */
private final HTTPContext http;
/**
* Constructor.
* @param hc HTTP context
*/
RestXqWadl(final HTTPContext hc) {
http = hc;
}
/**
* Returns a WADL description for all available URIs.
* @param modules available modules
* @return WADL description
*/
synchronized FElem create(final HashMap modules) {
// create root nodes
final FElem application = new FElem(WADL + "application", WADL_URI).declareNS();
final String base = http.req.getRequestURL().toString();
final FElem resources = elem("resources", application).add("base", base);
// create children
final TreeMap map = new TreeMap();
for(final RestXqModule mod : modules.values()) {
for(final RestXqFunction func : mod.functions()) {
final TokenObjMap xqdoc = func.function.doc();
final String path = func.path.toString();
final String methods = func.methods.toString().replaceAll("[^A-Z ]", "");
// create resource
final FElem resource = new FElem(WADL + "resource", WADL_URI).add("path", path);
map.put(path + "?" + methods, resource);
// add documentation for path variables
final Matcher var = Pattern.compile("\\$[^}]*").matcher(path);
while(var.find()) {
addParam(var.group().substring(1), "template", resource, xqdoc, func);
}
// create method, add function documentation
final FElem method = elem("method", resource).add("name", methods);
final TokenList descs = xqdoc != null ? xqdoc.get(DOC_DESCRIPTION) : null;
if(descs != null) for(final byte[] desc : descs) addDoc(desc, method);
// create request
final FElem request = elem("request", method);
for(final RestXqParam rxp : func.queryParams)
addParam(rxp.key, "query", request, xqdoc, func);
for(final RestXqParam rxp : func.formParams)
addParam(rxp.key, "query", request, xqdoc, func);
for(final RestXqParam rxp : func.headerParams)
addParam(rxp.key, "header", request, xqdoc, func);
// create response
final FElem response = elem("response", method);
final FElem representation = elem("representation", response);
representation.add("mediaType", HTTPContext.mediaType(func.output));
}
}
// add resources in sorted order
for(final FElem elem : map.values()) resources.add(elem);
return application;
}
/**
* Adds a parameter and its documentation to the specified element.
* @param name name of parameter
* @param style style
* @param root root element
* @param xqdoc documentation
* @param func function
*/
private void addParam(final String name, final String style, final FElem root,
final TokenObjMap xqdoc, final RestXqFunction func) {
final FElem param = elem("param", root);
param.add("name", name).add("style", style);
final QNm qn = new QNm(name);
for(final Var var : func.function.args) {
if(var.name.eq(qn) && var.declType != null) {
param.add("type", var.declType.toString());
}
}
addDoc(Inspect.doc(xqdoc, token(name)), param);
}
/**
* Creates an element.
* @param name name of element
* @param parent parent node
* @return element node
*/
private FElem elem(final String name, final FElem parent) {
final FElem elem = new FElem(WADL + name, WADL_URI);
if(parent != null) parent.add(elem);
return elem;
}
/**
* Adds a documentation element to the specified element.
* @param xqdoc documentation (may be {@code null})
* @param parent parent node
*/
private void addDoc(final byte[] xqdoc, final FElem parent) {
if(xqdoc == null) return;
final FElem doc = elem("doc", parent);
doc.namespaces().add(EMPTY, token(XHTML_URL));
Inspect.add(xqdoc, http.context(), doc);
}
}
basex-7.7.2/basex-api/src/main/java/org/basex/http/webdav/ 0000775 0000000 0000000 00000000000 12224530032 0023247 5 ustar 00root root 0000000 0000000 basex-7.7.2/basex-api/src/main/java/org/basex/http/webdav/BXAbstractResource.java 0000664 0000000 0000000 00000024345 12224530032 0027627 0 ustar 00root root 0000000 0000000 package org.basex.http.webdav;
import static org.basex.http.webdav.impl.Utils.*;
import static com.bradmcevoy.http.LockResult.*;
import java.io.*;
import java.util.*;
import org.basex.core.Prop;
import org.basex.http.webdav.impl.ResourceMetaData;
import org.basex.http.webdav.impl.WebDAVService;
import org.basex.util.*;
import com.bradmcevoy.http.*;
import com.bradmcevoy.http.exceptions.*;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;
/**
* WebDAV resource representing an abstract folder within a collection database.
*
* @author BaseX Team 2005-13, BSD License
* @author Rositsa Shadura
* @author Dimitar Popov
*/
public abstract class BXAbstractResource implements
CopyableResource, DeletableResource, MoveableResource, LockableResource {
/** Resource meta data. */
protected final ResourceMetaData meta;
/** WebDAV service implementation. */
protected final WebDAVService service;
/**
* Constructor.
* @param m resource meta data
* @param s service
*/
protected BXAbstractResource(final ResourceMetaData m,
final WebDAVService s) {
meta = m;
service = s;
}
@Override
public Object authenticate(final String user, final String pass) {
if(user != null)
new BXCode