Introduce file upload widget
authorMathieu Baudier <mbaudier@argeo.org>
Mon, 24 Jan 2011 13:20:35 +0000 (13:20 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Mon, 24 Jan 2011 13:20:35 +0000 (13:20 +0000)
git-svn-id: https://svn.argeo.org/commons/trunk@4072 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

35 files changed:
eclipse/rap/org.eclipse.rwt.widgets.upload/.classpath [new file with mode: 0644]
eclipse/rap/org.eclipse.rwt.widgets.upload/.project [new file with mode: 0644]
eclipse/rap/org.eclipse.rwt.widgets.upload/.settings/org.eclipse.core.resources.prefs [new file with mode: 0644]
eclipse/rap/org.eclipse.rwt.widgets.upload/.settings/org.eclipse.core.runtime.prefs [new file with mode: 0644]
eclipse/rap/org.eclipse.rwt.widgets.upload/.settings/org.eclipse.jdt.core.prefs [new file with mode: 0644]
eclipse/rap/org.eclipse.rwt.widgets.upload/.settings/org.eclipse.jdt.ui.prefs [new file with mode: 0644]
eclipse/rap/org.eclipse.rwt.widgets.upload/META-INF/MANIFEST.MF [new file with mode: 0644]
eclipse/rap/org.eclipse.rwt.widgets.upload/build.properties [new file with mode: 0644]
eclipse/rap/org.eclipse.rwt.widgets.upload/plugin.xml [new file with mode: 0644]
eclipse/rap/org.eclipse.rwt.widgets.upload/rap-sandbox-upload-widget.psf [new file with mode: 0644]
eclipse/rap/org.eclipse.rwt.widgets.upload/readme.txt [new file with mode: 0644]
eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/IUploadConfiguration.java [new file with mode: 0644]
eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/Upload.java [new file with mode: 0644]
eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/Upload.js [new file with mode: 0644]
eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/UploadAdapter.java [new file with mode: 0644]
eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/UploadEvent.java [new file with mode: 0644]
eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/UploadItem.java [new file with mode: 0644]
eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/UploadListener.java [new file with mode: 0644]
eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/internal/UploadConfiguration.java [new file with mode: 0644]
eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/internal/resource/UploadButtonResource.java [new file with mode: 0644]
eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/internal/resource/UploadFieldResource.java [new file with mode: 0644]
eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/internal/resource/UploadFormResource.java [new file with mode: 0644]
eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/internal/resource/UploadResource.java [new file with mode: 0644]
eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/internal/resource/qxcontrib/UploadButton.js [new file with mode: 0644]
eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/internal/resource/qxcontrib/UploadField.js [new file with mode: 0644]
eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/internal/resource/qxcontrib/UploadForm.js [new file with mode: 0644]
eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/internal/uploadkit/IUploadAdapter.java [new file with mode: 0644]
eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/internal/uploadkit/Upload.appearances.js [new file with mode: 0644]
eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/internal/uploadkit/UploadLCA.java [new file with mode: 0644]
eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/internal/uploadkit/UploadThemeAdapter.java [new file with mode: 0644]
eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/upload/servlet/FileUploadListener.java [new file with mode: 0644]
eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/upload/servlet/FileUploadServiceHandler.java [new file with mode: 0644]
eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/upload/servlet/FileUploadServlet.java [new file with mode: 0644]
eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/upload/servlet/FileUploadStorage.java [new file with mode: 0644]
eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/upload/servlet/FileUploadStorageItem.java [new file with mode: 0644]

diff --git a/eclipse/rap/org.eclipse.rwt.widgets.upload/.classpath b/eclipse/rap/org.eclipse.rwt.widgets.upload/.classpath
new file mode 100644 (file)
index 0000000..b7464f3
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+       <classpathentry kind="src" path="src"/>
+       <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.4"/>
+       <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/eclipse/rap/org.eclipse.rwt.widgets.upload/.project b/eclipse/rap/org.eclipse.rwt.widgets.upload/.project
new file mode 100644 (file)
index 0000000..d6f720b
--- /dev/null
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>org.eclipse.rwt.widgets.upload</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.jdt.core.javabuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.pde.ManifestBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.pde.SchemaBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.pde.PluginNature</nature>
+               <nature>org.eclipse.jdt.core.javanature</nature>
+       </natures>
+</projectDescription>
diff --git a/eclipse/rap/org.eclipse.rwt.widgets.upload/.settings/org.eclipse.core.resources.prefs b/eclipse/rap/org.eclipse.rwt.widgets.upload/.settings/org.eclipse.core.resources.prefs
new file mode 100644 (file)
index 0000000..828589b
--- /dev/null
@@ -0,0 +1,3 @@
+#Tue Apr 24 13:44:30 CEST 2007
+eclipse.preferences.version=1
+encoding/<project>=ISO-8859-1
diff --git a/eclipse/rap/org.eclipse.rwt.widgets.upload/.settings/org.eclipse.core.runtime.prefs b/eclipse/rap/org.eclipse.rwt.widgets.upload/.settings/org.eclipse.core.runtime.prefs
new file mode 100644 (file)
index 0000000..6adaf4d
--- /dev/null
@@ -0,0 +1,3 @@
+#Tue Dec 04 14:34:55 CET 2007
+eclipse.preferences.version=1
+line.separator=\n
diff --git a/eclipse/rap/org.eclipse.rwt.widgets.upload/.settings/org.eclipse.jdt.core.prefs b/eclipse/rap/org.eclipse.rwt.widgets.upload/.settings/org.eclipse.jdt.core.prefs
new file mode 100644 (file)
index 0000000..248b081
--- /dev/null
@@ -0,0 +1,328 @@
+#Tue May 05 00:08:54 CEST 2009
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=disabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.4
+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.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=warning
+org.eclipse.jdt.core.compiler.problem.autoboxing=error
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nullReference=ignore
+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.rawTypeReference=ignore
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.3
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=82
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=82
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=82
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=82
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=50
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=52
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=51
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=52
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=82
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=82
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=84
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=36
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=36
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=36
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=36
+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=1
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=0
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=0
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=0
+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=next_line_on_wrap
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=next_line_on_wrap
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=next_line_on_wrap
+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=next_line_on_wrap
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=next_line_on_wrap
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=true
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=true
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=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=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert
+org.eclipse.jdt.core.formatter.comment.line_length=80
+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=false
+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=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not 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=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=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=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=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=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=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=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=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=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=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=do not 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=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=80
+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=0
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=false
+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
diff --git a/eclipse/rap/org.eclipse.rwt.widgets.upload/.settings/org.eclipse.jdt.ui.prefs b/eclipse/rap/org.eclipse.rwt.widgets.upload/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644 (file)
index 0000000..ada8dbc
--- /dev/null
@@ -0,0 +1,9 @@
+#Tue Apr 15 13:03:32 CEST 2008
+eclipse.preferences.version=1
+formatter_profile=_rap
+formatter_settings_version=11
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=java;javax;org;com;
+org.eclipse.jdt.ui.ondemandthreshold=3
+org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates><template autoinsert\="true" context\="gettercomment_context" deleted\="false" description\="Comment for getter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.gettercomment" name\="gettercomment"/><template autoinsert\="true" context\="settercomment_context" deleted\="false" description\="Comment for setter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.settercomment" name\="settercomment"/><template autoinsert\="true" context\="constructorcomment_context" deleted\="false" description\="Comment for created constructors" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorcomment" name\="constructorcomment"/><template autoinsert\="true" context\="filecomment_context" deleted\="false" description\="Comment for created Java files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.filecomment" name\="filecomment">/**\r\n * \r\n */</template><template autoinsert\="true" context\="typecomment_context" deleted\="false" description\="Comment for created types" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.typecomment" name\="typecomment">/**\r\n * @author ${user} */</template><template autoinsert\="true" context\="fieldcomment_context" deleted\="false" description\="Comment for fields" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment"/><template autoinsert\="true" context\="methodcomment_context" deleted\="false" description\="Comment for non-overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodcomment" name\="methodcomment"/><template autoinsert\="true" context\="overridecomment_context" deleted\="false" description\="Comment for overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.overridecomment" name\="overridecomment"/><template autoinsert\="true" context\="delegatecomment_context" deleted\="false" description\="Comment for delegate methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.delegatecomment" name\="delegatecomment">/**\r\n * ${tags}\r\n * ${see_to_target}\r\n */</template><template autoinsert\="false" context\="newtype_context" deleted\="false" description\="Newly created files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.newtype" name\="newtype">/*******************************************************************************\r\n * Copyright (c) 2002-2006 Innoopract Informationssysteme GmbH.\r\n * All rights reserved. This program and the accompanying materials\r\n * are made available under the terms of the Eclipse Public License v1.0\r\n * which accompanies this distribution, and is available at\r\n * http\://www.eclipse.org/legal/epl-v10.html\r\n * \r\n * Contributors\:\r\n *     Innoopract Informationssysteme GmbH - initial API and implementation\r\n ******************************************************************************/\r\n\r\n${package_declaration}\r\n\r\n${typecomment}\r\n${type_declaration}</template><template autoinsert\="true" context\="classbody_context" deleted\="false" description\="Code in new class type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.classbody" name\="classbody">\r\n</template><template autoinsert\="true" context\="interfacebody_context" deleted\="false" description\="Code in new interface type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.interfacebody" name\="interfacebody">\r\n</template><template autoinsert\="true" context\="enumbody_context" deleted\="false" description\="Code in new enum type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.enumbody" name\="enumbody">\r\n</template><template autoinsert\="true" context\="annotationbody_context" deleted\="false" description\="Code in new annotation type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.annotationbody" name\="annotationbody">\r\n</template><template autoinsert\="true" context\="catchblock_context" deleted\="false" description\="Code in new catch blocks" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.catchblock" name\="catchblock">// ${todo} Auto-generated catch block\r\n${exception_var}.printStackTrace();</template><template autoinsert\="true" context\="methodbody_context" deleted\="false" description\="Code in created method stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodbody" name\="methodbody">${body_statement}</template><template autoinsert\="true" context\="constructorbody_context" deleted\="false" description\="Code in created constructor stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorbody" name\="constructorbody">${body_statement}</template><template autoinsert\="true" context\="getterbody_context" deleted\="false" description\="Code in created getters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.getterbody" name\="getterbody">return ${field};</template><template autoinsert\="true" context\="setterbody_context" deleted\="false" description\="Code in created setters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.setterbody" name\="setterbody">${field} \= ${param};</template></templates>
diff --git a/eclipse/rap/org.eclipse.rwt.widgets.upload/META-INF/MANIFEST.MF b/eclipse/rap/org.eclipse.rwt.widgets.upload/META-INF/MANIFEST.MF
new file mode 100644 (file)
index 0000000..1c1623c
--- /dev/null
@@ -0,0 +1,13 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %Bundle-Name
+Bundle-Vendor: %Bundle-Vendor
+Bundle-SymbolicName: org.eclipse.rwt.widgets.upload;singleton:=true
+Bundle-Version: 1.0.0.qualifier
+Require-Bundle: org.eclipse.rap.rwt,
+ org.apache.commons.fileupload;bundle-version="1.2.0",
+ org.apache.commons.io;bundle-version="1.3.2"
+Export-Package: org.eclipse.rwt.widgets
+Import-Package: javax.servlet;version="[2.3.0,3.0.0]",
+ javax.servlet.http;version="[2.3.0,3.0.0]"
+Bundle-RequiredExecutionEnvironment: J2SE-1.4
diff --git a/eclipse/rap/org.eclipse.rwt.widgets.upload/build.properties b/eclipse/rap/org.eclipse.rwt.widgets.upload/build.properties
new file mode 100644 (file)
index 0000000..3f0d0e4
--- /dev/null
@@ -0,0 +1,5 @@
+output.. = target/classes/
+bin.includes = META-INF/,\
+               plugin.xml,\
+               .
+source.. = src/
diff --git a/eclipse/rap/org.eclipse.rwt.widgets.upload/plugin.xml b/eclipse/rap/org.eclipse.rwt.widgets.upload/plugin.xml
new file mode 100644 (file)
index 0000000..b64e380
--- /dev/null
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.2"?>
+<plugin>
+    <extension point="org.eclipse.rap.ui.themeableWidgets">
+        <widget
+            class="org.eclipse.rwt.widgets.Upload"
+            id="org.eclipse.rwt.widgets.upload"
+            name="upload">
+        </widget>
+    </extension>
+    <extension point="org.eclipse.rap.ui.resources">
+        <resource class="org.eclipse.rwt.widgets.internal.resource.UploadButtonResource"/>
+        <resource class="org.eclipse.rwt.widgets.internal.resource.UploadResource"/>
+        <resource
+              class="org.eclipse.rwt.widgets.internal.resource.UploadFieldResource">
+        </resource>
+        <resource
+              class="org.eclipse.rwt.widgets.internal.resource.UploadFormResource">
+        </resource>
+    </extension>
+    <extension point="org.eclipse.equinox.http.registry.servlets">
+        <servlet
+              alias="/upload"
+              class="org.eclipse.rwt.widgets.upload.servlet.FileUploadServlet"
+              httpcontextId="org.eclipse.rap.httpcontext"
+              load-on-startup="false">
+        </servlet>
+    </extension>
+</plugin>
diff --git a/eclipse/rap/org.eclipse.rwt.widgets.upload/rap-sandbox-upload-widget.psf b/eclipse/rap/org.eclipse.rwt.widgets.upload/rap-sandbox-upload-widget.psf
new file mode 100644 (file)
index 0000000..20612bc
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<psf version="2.0">
+<provider id="org.eclipse.team.cvs.core.cvsnature">
+<project reference="1.0,:pserver:anonymous@dev.eclipse.org:/cvsroot/tools,org.eclipse.orbit/org.apache.commons.fileupload,org.apache.commons.fileupload,v1_2"/>
+<project reference="1.0,:pserver:anonymous@dev.eclipse.org:/cvsroot/tools,org.eclipse.orbit/org.apache.commons.io,org.apache.commons.io,v1_3_2"/>
+<project reference="1.0,:pserver:anonymous@dev.eclipse.org:/cvsroot/rt,org.eclipse.rap/sandbox/org.eclipse.rwt.widgets.upload,org.eclipse.rwt.widgets.upload"/>
+<project reference="1.0,:pserver:anonymous@dev.eclipse.org:/cvsroot/rt,org.eclipse.rap/sandbox/org.eclipse.rwt.widgets.upload.demo,org.eclipse.rwt.widgets.upload.demo"/>
+</provider>
+</psf>
diff --git a/eclipse/rap/org.eclipse.rwt.widgets.upload/readme.txt b/eclipse/rap/org.eclipse.rwt.widgets.upload/readme.txt
new file mode 100644 (file)
index 0000000..d298de9
--- /dev/null
@@ -0,0 +1,19 @@
+If you get compile error you can use the supplied Team Project Set file
+"rap-sandbox-upload-widget.psf", to check out all necessary projects
+into your workspace.
+
+1. Select "rap-sandbox-uploadwidget.psf"
+2. Right click
+3. Choose "Import Project Set..."
+4. Follow the instructions in the dialog
+
+The project set file will add these projects to your workspace:
+
+org.apache.commons.fileupload (v1_2)
+org.apache.commons.io (v_1_3_2)
+org.eclipse.rwt.widgets.uploads.demo (optional, contains an example)
+
+If you have further questions, post to the RAP newsgroup:
+http://www.eclipse.org/rap/newsgroup.php
+
+Have fun!
diff --git a/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/IUploadConfiguration.java b/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/IUploadConfiguration.java
new file mode 100644 (file)
index 0000000..21ac68c
--- /dev/null
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2002-2006 Innoopract Informationssysteme GmbH. All rights
+ * reserved. This program and the accompanying materials are made available
+ * under the terms of the Eclipse Public License v1.0 which accompanies this
+ * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html
+ * Contributors: Innoopract Informationssysteme GmbH - initial API and
+ * implementation
+ ******************************************************************************/
+package org.eclipse.rwt.widgets;
+
+import org.apache.commons.fileupload.FileUploadBase;
+
+/**
+ * Provides a configuration mechanism for the file upload. Note that this
+ * configuration is shared for all upload widgets.
+ * 
+ * @author Stefan.Roeck
+ */
+public interface IUploadConfiguration {
+
+  /**
+   *@see FileUploadBase#setFileSizeMax(long)
+   */
+  public void setFileMaxSize( long fileSizeMax );
+
+  /**
+   *@see FileUploadBase#getFileSizeMax()
+   */
+  public long getFileSizeMax();
+
+  /**
+   *@see FileUploadBase#setSizeMax(long)
+   */
+  public void setSizeMax( long sizeMax );
+
+  /**
+   *@see FileUploadBase#getSizeMax()
+   */
+  public long getSizeMax();
+}
diff --git a/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/Upload.java b/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/Upload.java
new file mode 100644 (file)
index 0000000..f087a70
--- /dev/null
@@ -0,0 +1,623 @@
+/*******************************************************************************
+ * Copyright (c) 2002-2007 Critical Software S.A. All rights reserved. This
+ * program and the accompanying materials are made available under the terms of
+ * the Eclipse Public License v1.0 which accompanies this distribution, and is
+ * available at http://www.eclipse.org/legal/epl-v10.html Contributors: Tiago
+ * Rodrigues (Critical Software S.A.) - initial implementation Joel Oliveira
+ * (Critical Software S.A.) - initial commit
+ ******************************************************************************/
+package org.eclipse.rwt.widgets;
+
+import java.io.File;
+
+import org.eclipse.rwt.graphics.Graphics;
+import org.eclipse.rwt.internal.theme.IThemeAdapter;
+import org.eclipse.rwt.widgets.internal.uploadkit.IUploadAdapter;
+import org.eclipse.rwt.widgets.internal.uploadkit.UploadThemeAdapter;
+import org.eclipse.rwt.widgets.upload.servlet.*;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * Widget representing an Upload box.
+ *
+ * @author tjarodrigues
+ * @author stefan.roeck
+ */
+public class Upload extends Control {
+  /**
+   * Displays a progress bar inside the widget.
+   */
+  public final static int SHOW_PROGRESS = 1;
+
+  /**
+   * Fires progress events to registered UploadListeners.
+   * If this flag is not set, only the {@link UploadListener#uploadFinished()}
+   * event is fired.
+   * @see UploadListener#uploadInProgress(UploadEvent)
+   */
+  public final static int FIRE_PROGRESS_EVENTS = 4;
+  /**
+   * Displays a upload button next to the browse button.
+   */
+  public final static int SHOW_UPLOAD_BUTTON = 2;
+
+  static {
+    // TODO: [sr] move to extension point if existent
+    // Register FileUploadServiceHandler
+    FileUploadServiceHandler.register();
+  }
+
+  private String lastFileUploaded;
+  private final String servlet;
+  private String path;
+  private boolean performUpload = false;
+  private boolean resetUpload = false;
+  private int flags;
+  private UploadLCAAdapter uploadLCAAdapter;
+  private String browseButtonText = "Browse";
+  private String uploadButtonText = "Upload";
+  private boolean[] uploadInProgresses = { false };
+
+  // avoid exposure of upload internal stuff
+  private final class UploadLCAAdapter implements IUploadAdapter {
+    public boolean performUpload() {
+      boolean result = Upload.this.performUpload;
+      Upload.this.performUpload = false;
+      return result;
+    }
+
+    public int getFlags() {
+      return flags;
+    }
+
+    public void setPath( final String path ) {
+      // TODO: [sr] Frank, why not throw this event within readData of the LCA?
+      // Its quite hidden here :-)
+      if( path != null ) {
+        if( !path.equals( Upload.this.path ) ) {
+          Upload.this.path = path;
+          ModifyEvent modifyEvent = new ModifyEvent( Upload.this );
+          modifyEvent.processEvent();
+        }
+      }
+    }
+
+    public void setLastFileUploaded( final String lastFileUploaded ) {
+      Upload.this.lastFileUploaded = lastFileUploaded;
+    }
+
+    public String getServletPath() {
+      return Upload.this.servlet;
+    }
+
+    public boolean isResetUpload() {
+      return Upload.this.resetUpload;
+    }
+
+    public void setResetUpload( boolean resetUpload ) {
+      Upload.this.resetUpload = resetUpload;
+    }
+
+    public long getBytesRead() {
+      final FileUploadStorageItem uploadStorageItem = FileUploadStorage.getInstance().getUploadStorageItem( getWidgetId());
+      return uploadStorageItem != null ? uploadStorageItem.getBytesRead() : 0L;
+    }
+
+    public FileUploadStorageItem getStorageItem() {
+      return Upload.this.getUploadStorageItem();
+    }
+
+    public long getContentLength() {
+      final FileUploadStorageItem uploadStorageItem = FileUploadStorage.getInstance().getUploadStorageItem( getWidgetId());
+      return uploadStorageItem != null ? uploadStorageItem.getContentLength() : 0L;
+    }
+  }
+
+
+  /**
+   * Initializes the Upload.
+   *
+   * @param parent Parent container.
+   * @param style Widget style.
+   * @param servlet The upload servlet name.
+   * @param showProgress Indicates if the progress bar should be visible.
+   * @deprecated use Upload(Composite, int, int) instead
+   */
+  public Upload( final Composite parent,
+                 final int style,
+                 final String servlet,
+                 final boolean showProgress )
+  {
+    this( parent,
+          style,
+          servlet,
+          ( showProgress ? SHOW_PROGRESS : 0 ) | SHOW_UPLOAD_BUTTON );
+  }
+
+  /**
+   * @deprecated use Upload(Composite, int, int) instead
+   */
+  public Upload( final Composite parent,
+                 final int style,
+                 final String servlet )
+  {
+    this( parent, style, servlet, 0 );
+  }
+
+  /**
+   * @deprecated use Upload(Composite, int, int) instead
+   */
+  public Upload( final Composite parent,
+                 final int style,
+                 final String servlet,
+                 final int flags )
+  {
+    super( parent, style );
+    this.servlet = ( ( servlet == null ) ? FileUploadServiceHandler.getUrl(getWidgetId()) : servlet );
+    this.flags = flags;
+
+    if ((this.flags & SHOW_PROGRESS) > 0) {
+      this.flags |= FIRE_PROGRESS_EVENTS;
+    }
+
+    this.lastFileUploaded = "";
+    this.path = "";
+
+    // Add a fileStorage item which is used for transfering the uploaded file
+    FileUploadStorage.getInstance().setUploadStorageItem( getWidgetId(), new FileUploadStorageItem() );
+  }
+
+  /**
+   * Constructs a upload widget.
+   * @param style Supported styles:
+   * {@link SWT#BORDER}
+   * @param flags supported flags:
+   * {@link Upload#SHOW_PROGRESS}
+   * {@link Upload#SHOW_UPLOAD_BUTTON}
+   * {@link Upload#FIRE_PROGRESS_EVENTS}
+   * The SHOW_PROGRESS flag implies the flag FIRE_PROGRESS_EVENTS.
+   */
+  public Upload( final Composite parent,
+                 final int style,
+                 final int flags )
+  {
+    this (parent, style, null, flags);
+  }
+
+  /**
+   * Convenience constructor for creating an upload widget without upload
+   * button and progress bar. Same as {@link Upload(parent,int,int)} with 0 as
+   * value for the flags parameter.
+   */
+  public Upload( final Composite parent,
+                 final int style )
+  {
+    this( parent, style, null, 0 );
+  }
+
+
+  /**
+   * Gets the servlet.
+   *
+   * @return Servlet name.
+   * @deprecated This method will be removed in a future version as the servlet
+   * is only used internally and cannot be set from outside anymore.
+   */
+  public String getServlet() {
+    checkWidget();
+    return servlet;
+  }
+
+  /**
+   * Returns the full file name of the last
+   * uploaded file including the file path as
+   * selected by the user on his local machine.
+   * <br>
+   * The full path including the directory and file
+   * drive are only returned, if the browser supports
+   * reading this properties. In Firefox 3, only
+   * the filename is returned.
+   * @see Upload#getLastFileUploaded()
+   */
+  public String getPath() {
+    checkWidget();
+    return path;
+  }
+
+  /**
+   * Triggers a file upload. This method immediately returns, if the user hasn't
+   * selected a file, yet. Otherwise, a upload is triggered on the Browser side.
+   * This method returns, if the upload has finished.
+   * <br/>
+   * Note: This method doesn't fire exceptions. Instead, see {@link #addUploadListener(UploadListener)}
+   * and {@link UploadEvent#getUploadException()} on how to get notified about exceptions during upload.
+   * @return <code>true</code> if the upload has been started and has finished
+   * without an error.
+   * @see Upload#addUploadListener(UploadListener)
+   */
+  public boolean performUpload() {
+    checkWidget();
+
+    // Clean state (from previous uploads)
+    resetStorageItem();
+
+    final boolean uploadSuccessful[] = {false};
+    // Always check if user selected a file because otherwise the UploadWidget itself doesn't trigger a POST and therefore, the
+    // subsequent loop never terminates.
+    if (getPath() != null && !"".equals( getPath() )) {
+      if( isEnabled() && !uploadInProgresses[ 0 ] ) {
+        performUpload = true;
+        UploadListener listener =  new UploadAdapter() {
+          public void uploadFinished(UploadEvent event) {
+            uploadInProgresses[ 0 ] = false;
+            uploadSuccessful[ 0 ] = true;
+          }
+
+          public void uploadException( UploadEvent uploadEvent ) {
+            uploadInProgresses[ 0 ] = false;
+          }
+        };
+        addUploadListener( listener );
+        uploadInProgresses[ 0 ] = true;
+        try {
+          while( uploadInProgresses[ 0 ] && !isDisposed()) {
+            if( !getDisplay().readAndDispatch() ) {
+              getDisplay().sleep();
+            }
+          }
+        } finally {
+          uploadInProgresses[ 0 ] = false;
+          performUpload = false;
+          // 324732: [upload] Widget is disposed if widget is disposed while upload is in progress
+          // https://bugs.eclipse.org/bugs/show_bug.cgi?id=324732
+          if (!isDisposed()) {
+            removeUploadListener( listener );
+          }
+        }
+    }
+
+    }
+    return uploadSuccessful[ 0 ];
+  }
+
+  public Object getAdapter( final Class adapter ) {
+    Object result;
+    if( adapter == IUploadAdapter.class ) {
+      if( uploadLCAAdapter == null ) {
+        uploadLCAAdapter = new UploadLCAAdapter();
+      }
+      result = uploadLCAAdapter;
+    } else {
+      result = super.getAdapter( adapter );
+    }
+    return result;
+  }
+
+  // TODO [fappel]: improve this preliminary compute size implementation
+  public Point computeSize( final int wHint,
+                            final int hHint,
+                            final boolean changed )
+  {
+    Point browseButtonSize = computeBrowseButtonSize();
+
+    int browseButtonHeight = browseButtonSize.y;
+    int progressHeight = 20;
+
+    int height = 0, width = 0;
+    if( wHint == SWT.DEFAULT || hHint == SWT.DEFAULT ) {
+      if( ( ( flags & SHOW_PROGRESS ) > 0 )
+          && ( ( flags & SHOW_UPLOAD_BUTTON ) > 0 ) )
+      {
+        // progress bar and upload button visible
+        width = computeBaseWidth();
+        final Point textExtent = Graphics.stringExtent( getFont(), getUploadButtonText());
+        width += textExtent.x;
+
+        height = Math.max( computeBaseHeight(),
+                           Math.max( textExtent.y, browseButtonHeight ) );
+
+        height += progressHeight;
+
+      } else if( ( flags & SHOW_PROGRESS ) > 0 ) {
+        // progress bar visible
+        width = computeBaseWidth();
+        height = Math.max( computeBaseHeight(), browseButtonHeight );
+        height += progressHeight;
+
+      } else if( ( flags & SHOW_UPLOAD_BUTTON ) > 0 ) {
+        // upload button visible
+        width = computeBaseWidth();
+
+        final Point textExtent = Graphics.stringExtent( getFont(), getUploadButtonText());
+        width += textExtent.x;
+
+        height = Math.max( computeBaseHeight(),
+                           Math.max( textExtent.y, browseButtonHeight ) );
+
+      } else {
+        // no progress bar and no upload button visible
+        width = computeBaseWidth();
+        height = Math.max( computeBaseHeight(), browseButtonHeight );
+      }
+    }
+
+    if( wHint != SWT.DEFAULT ) {
+      width = wHint;
+    }
+
+    if( hHint != SWT.DEFAULT ) {
+      height = hHint;
+    }
+
+    return new Point( width, height +2);
+  }
+
+  private int computeBaseHeight() {
+    return Graphics.getCharHeight( getFont() );
+  }
+
+  /**
+   * These lines are copied from {@link Button#computeSize(int, int)}.
+   * TODO: [sr] Find a better solution to avoid this code duplication...
+   */
+  private Point computeBrowseButtonSize() {
+    final int border = getButtonBorder();
+    int width = 0, height = 0;
+
+    final Point extent = Graphics.stringExtent( getFont(), getBrowseButtonText() );
+    height = Math.max( height, extent.y );
+    width += extent.x;
+
+    width += 12;
+    height += 10;
+
+    width += border * 2;
+    height += border * 2;
+    return new Point( width, height );
+  }
+
+  private int getButtonBorder() {
+    UploadThemeAdapter themeAdapter
+      = ( UploadThemeAdapter )getAdapter( IThemeAdapter.class );
+    return themeAdapter.getButtonBorderWidth( this );
+  }
+
+  private int computeBaseWidth() {
+    float avgCharWidth = Graphics.getAvgCharWidth( getFont() );
+    return ( int )( avgCharWidth * 50 );
+  }
+
+  /**
+   * Set the text of the browse button.
+   */
+  public void setBrowseButtonText( final String browseButtonText ) {
+    checkWidget();
+    if( browseButtonText == null ) {
+      SWT.error( SWT.ERROR_NULL_ARGUMENT );
+    }
+    this.browseButtonText = browseButtonText;
+  }
+
+  /**
+   * Returns the text of the browse button.
+   */
+  public String getBrowseButtonText() {
+    checkWidget();
+    return browseButtonText;
+  }
+
+  /**
+   * Sets the text of the upload button. Only applies, if {@link #SHOW_UPLOAD_BUTTON}
+   * is set as style.
+   * @param Text for the upload button, must not be <code>null</code>.
+   * @see #Upload(Composite, int, int)
+   */
+  public void setUploadButtonText( final String uploadButtonText ) {
+    checkWidget();
+    if( uploadButtonText == null ) {
+      SWT.error( SWT.ERROR_NULL_ARGUMENT );
+    }
+    this.uploadButtonText = uploadButtonText;
+  }
+
+  /**
+   * Returns the text of the upload button. Can return <code>null</code>.
+   */
+  public String getUploadButtonText() {
+    checkWidget();
+    return uploadButtonText;
+  }
+
+  /**
+   * Adds the listener to the collection of listeners who will
+   * be notified when the receiver's path is modified, by sending
+   * it one of the messages defined in the <code>ModifyListener</code>
+   * interface.
+   *
+   * @param listener the listener which should be notified
+   *
+   * @exception IllegalArgumentException <ul>
+   *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+   * </ul>
+   * @exception SWTException <ul>
+   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+   * </ul>
+   *
+   * @see ModifyListener
+   * @see #removeModifyListener
+   */
+  public void addModifyListener( final ModifyListener listener ) {
+    checkWidget();
+    ModifyEvent.addListener( this, listener );
+  }
+
+  /**
+   * Removes the listener from the collection of listeners who will
+   * be notified when the receiver's path is modified.
+   *
+   * @param listener the listener which should no longer be notified
+   *
+   * @exception IllegalArgumentException <ul>
+   *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+   * </ul>
+   * @exception SWTException <ul>
+   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+   * </ul>
+   *
+   * @see ModifyListener
+   * @see #addModifyListener
+   */
+  public void removeModifyListener( final ModifyListener listener ) {
+    checkWidget();
+    ModifyEvent.removeListener( this, listener );
+  }
+
+  /**
+   * Gets the name of the last uploaded file. This method
+   * can be called even if the upload has not finished yet.
+   * @see Upload#getPath()
+   *
+   * @return The name of the last uploaded file.
+   */
+  public String getLastFileUploaded() {
+    checkWidget();
+    return lastFileUploaded;
+  }
+
+  /**
+   * Returns the <code>java.io.File<code> that represents the absolute
+   * path to the last uploaded file disk.
+   *
+   * @return The <code>java.io.File<code> that represents the absolute
+   * path to the last uploaded file disk or null if no file was uploaded. The
+   * latter may be the case if the path entered by the user doesn't exist.
+   * @deprecated This method is no longer supported and always returns null.
+   * Please use {@link Upload#getUploadItem()} instead.
+   */
+  public File getLastUploadedFile() {
+    checkWidget();
+    return null;
+//    HttpSession session = RWT.getSessionStore().getHttpSession();
+//    File tmpDir = FileUploadServlet.getUploadTempDir( session );
+//    File result = new File( tmpDir, lastFileUploaded );
+//    if( !result.exists() ) {
+//      result = null;
+//    }
+//    return result;
+  }
+
+
+  /**
+   * After uploading has finished this method returns the uploaded file
+   * and all available meta data, as file name, content type, etc.
+   * @throws SWTException SWT.ERROR_WIDGET_DISPOSED if widget is disposed.
+   */
+  public UploadItem getUploadItem() {
+    checkWidget();
+
+    // TODO: [sr] remove if implemented in Widget#checkWidget()
+    if (isDisposed()) {
+      SWT.error( SWT.ERROR_WIDGET_DISPOSED );
+    }
+
+    final FileUploadStorageItem uploadedFile = getUploadStorageItem();
+    final UploadItem uploadItem = new UploadItem( uploadedFile.getFileInputStream(),
+                                                  uploadedFile.getContentType(),
+                                                  getLastFileUploaded(),
+                                                  getPath(),
+                                                  uploadedFile.getContentLength());
+    return uploadItem;
+  }
+
+  private String getWidgetId() {
+    return String.valueOf(this.hashCode());
+  }
+
+  /**
+   * Sets the name of the last uploaded file.
+   *
+   * @param lastFileUploaded The name of the last uploaded file.
+   * @deprecated This method should not be used and will be removed
+   * in a future version because the semantics don't make sense.
+   */
+  public void setLastFileUploaded( final String lastFileUploaded ) {
+    checkWidget();
+    this.lastFileUploaded = lastFileUploaded;
+  }
+
+  /**
+   * Adds a new Listener to the Upload.
+   *
+   * @param listener The new listener.
+   */
+  public void addUploadListener( final UploadListener listener ) {
+    checkWidget();
+    UploadEvent.addListener( this, listener );
+
+  }
+
+  /**
+   * Removes a Listener from the Upload.
+   *
+   * @param listener The new listener.
+   */
+  public void removeUploadListener( final UploadListener listener ) {
+    checkWidget();
+    UploadEvent.removeListener( this, listener );
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public void dispose() {
+    FileUploadStorage.getInstance().setUploadStorageItem( getWidgetId(), null );
+    super.dispose();
+  }
+
+  /**
+   * Resets the internal state of the widget so that all information about the last
+   * uploaded file are lost. Additionally the text and the progressbar (if visible)
+   * are reset to the defaults.
+   */
+  public void reset() {
+    checkWidget();
+
+    this.lastFileUploaded = "";
+    this.path = "";
+
+    resetStorageItem();
+
+    resetUpload = true;
+  }
+
+  /**
+   * Resets the internal storage item that is used to transfer the file content
+   * and progress between widget and ServiceHandler.
+   */
+  private void resetStorageItem() {
+    final FileUploadStorageItem storageItem = FileUploadStorage.getInstance().getUploadStorageItem( getWidgetId() );
+    storageItem.reset();
+  }
+
+  /**
+   * Returns a configuration facade. Note that this configuration
+   * is shared for all update widgets.
+   */
+  public IUploadConfiguration getConfiguration() {
+    return FileUploadServiceHandler.getConfiguration();
+  }
+
+  protected FileUploadStorageItem getUploadStorageItem() {
+    final FileUploadStorage storage = FileUploadStorage.getInstance();
+    final FileUploadStorageItem uploadedFile = storage.getUploadStorageItem( getWidgetId() );
+    return uploadedFile;
+  }
+
+}
diff --git a/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/Upload.js b/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/Upload.js
new file mode 100644 (file)
index 0000000..b7fc7f9
--- /dev/null
@@ -0,0 +1,343 @@
+/*******************************************************************************
+ * Copyright (c) 2002-2007 Critical Software S.A.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Tiago Rodrigues (Critical Software S.A.) - initial implementation
+ *     Joel Oliveira (Critical Software S.A.) - initial commit
+ ******************************************************************************/
+qx.Class.define( "org.eclipse.rwt.widgets.Upload", {
+  extend: qx.ui.layout.VerticalBoxLayout,
+
+  construct : function( servlet, flags ) {
+    this.base( arguments );
+
+    this._servlet = servlet;
+    this._isStarted = false;
+    
+    /*
+     * Identifies a upload process at the server.
+     */
+    this._uploadProcessId = "";
+    
+    /*
+     * Is used to retry sending a progress polling
+     * request only once.
+     */
+    this._monitorRequestFailed = false;
+    
+    this._showProgress = ( flags & 1 ) > 0;
+    this._showUploadButton = ( flags & 2 ) > 0;
+    this._fireProgressEvents = ( flags & 4 ) > 0;
+
+    this.initHeight();
+    this.initOverflow();
+
+    var topLayout = new qx.ui.layout.HorizontalBoxLayout();
+    topLayout.set({left:0,right:0,height:"1*"});
+
+    // Upload Form
+    this._uploadForm = new uploadwidget.UploadForm("uploadForm", this._servlet);
+    // Make the widget use the entire assigned space
+    this._uploadForm.set({top:0,left:0,width:"1*", height:"100%"});
+    topLayout.add(this._uploadForm);
+    
+
+    // Browse File Button
+    this._uploadField = new uploadwidget.UploadField("uploadFile", "Browse");
+    this._uploadField.set({left:0,right:0});
+    this._uploadField.addEventListener( "changeValue", this._onChangeValue, this );
+    
+    // workaround adjust browse button position
+    // Set default width for default text "Browse"
+    this._uploadField._button.set({top:0,right:0,height:"100%"});
+    this._uploadField._text.set({marginTop:0});
+
+    this._uploadForm.add(this._uploadField);
+    
+       this._uploadField.setHeight("100%");
+       this._uploadField._text.setHeight("100%");
+
+    // Upload Button
+    if( this._showUploadButton ) {
+      this._uploadButton = new qx.ui.form.Button("Upload");
+       
+      // This state is needed for proper button CSS themeing
+      this._uploadButton.addState( "rwt_PUSH" );
+      this._uploadButton.addEventListener("click", this._uploadFile, this);
+      this._uploadButton.set({height:"100%"});
+      topLayout.add(this._uploadButton);
+    }
+
+    this.add(topLayout);
+
+    if (this._showProgress) {
+        // Progress Bar
+        this._progressBar = new org.eclipse.swt.widgets.ProgressBar();
+        this._progressBar.set({left:0,height:20});
+        this._progressBar.setMinimum(0);
+        this._progressBar.setMaximum(100);
+        this._progressBar.setFlag(org.eclipse.swt.widgets.ProgressBar.FLAG_HORIZONTAL);
+        
+        this.add(this._progressBar);
+    }
+    
+    if (this._fireProgressEvents) {
+           this._uploadForm.addEventListener("sending", this._monitorUpload, this);
+    }
+    
+    this._uploadForm.addEventListener("completed", this._cleanUp, this);
+    this.addEventListener("upload", this._fireEvent, this);
+    this.addEventListener( "changeEnabled", this._onEnabled, this );
+    this._uploadField._button.addEventListener( "click", this._onFocus, this );
+  },
+  
+  destruct : function() {   
+       // SR: Seems as if _uploadField's button has already been disposed in some cases,
+       // e.g. if the user reloads the application pressing F5.
+       // See 275144: [Upload] Contextual JS errors with the upload widget
+    if (this._uploadField._button) {
+       this._uploadField._button.removeEventListener( "click", this._onFocus );
+    }
+    this.removeEventListener( "changeEnabled", this._onEnabled );
+    this._uploadField.removeEventListener( "changeValue", this._onChangeValue );
+    
+    if( this._showUploadButton ) {
+      this._uploadButton.removeEventListener("click", this._uploadFile);
+    }
+    
+    if (this._fireProgressEvents) {
+        this._uploadForm.removeEventListener("sending", this._monitorUpload);
+    }
+    
+    this._uploadForm.removeEventListener("completed", this._cleanUp);
+
+    this.removeEventListener("upload", this._fireEvent);
+  },        
+
+  events: {
+    "upload" : "qx.event.type.DataEvent"
+  },
+
+  properties :
+  {
+    /**
+     * The last file that was uploaded.
+     */
+    lastFileUploaded :
+    {
+      check : "String",
+      init  : ""
+    }
+  },
+
+  members : {
+    _fireEvent : function (e) {
+        var wm = org.eclipse.swt.WidgetManager.getInstance();
+        var id = wm.findIdByWidget(this);
+        var req = org.eclipse.swt.Request.getInstance();
+        req.addParameter(id + ".finished", e.getData());
+        req.addParameter(id + ".lastFileUploaded", this.getLastFileUploaded());
+        req.send();
+    },
+
+    _cleanUp : function () {
+        if (this._isStarted == true) {
+            var filename = this._uploadField.getValue();
+            
+            if (filename.indexOf("\\") != -1) {
+                filename = filename.substr(filename.lastIndexOf("\\") + 1);
+            } else if (filename.indexOf("/") != -1) {
+                filename = filename.substr(filename.lastIndexOf("/") + 1);
+            }                
+            
+            this.setLastFileUploaded(filename);
+            // Stefan Röck: The field shouldn't be cleaned automatically, this can
+            // still be achvied by calling reset()
+            //this._uploadField.setValue("");
+            //if( this._showProgress ) {
+            //  this._progressBar.setWidth("0%");
+            // }
+            
+            // make sure, that the progressbar (if visible) is filled completely after 
+            // uploading finished
+            if (this._showProgress) {
+              this._progressBar.setSelection(100);
+            }
+            this._isStarted = false;
+    
+            this.createDispatchDataEvent("upload", true);
+        }
+    },
+
+    /*
+     * Each upload process uses a unique id to allow the server
+     * to identify the incoming requests to return the correct upload 
+     * progress.
+     */
+    _generateUniqueUploadUrl : function () {
+        // generate a new id for this upload
+        this._uploadProcessId = new Date().valueOf();
+        
+        this._uploadForm.setUrl(this._getUniqueUploadUrl());
+    },
+    
+    /*
+     * Attaches the upload process id to the servlet url.
+     */
+    _getUniqueUploadUrl : function () {
+        var hasUrlParameter = this._servlet && this._servlet.indexOf("&");
+        var newUploadUrl;
+        if (hasUrlParameter != -1) {
+               newUploadUrl = this._servlet + "&processId=" + this._uploadProcessId;
+        } else {
+               newUploadUrl = this._servlet + "?processId=" + this._uploadProcessId;
+        }
+       return newUploadUrl;
+    },
+
+    _uploadFile : function () {
+        if (this._uploadField.getValue() != "") {
+            this._isStarted = true;
+            this._monitorRequestFailed = false;
+            this._generateUniqueUploadUrl();
+            this._uploadForm.send();
+        }
+    },
+    
+    _monitorUpload : function () {
+       qx.ui.core.Widget.flushGlobalQueues();
+               var req = new qx.io.remote.Request( this._getUniqueUploadUrl(), qx.net.Http.METHOD_GET, qx.util.Mime.TEXT );
+               req.setAsynchronous( false );
+               req.addEventListener( "completed", this._handleCompleted, this );
+               req.send();
+    },
+    
+    _handleCompleted : function( evt ) {
+       var req = evt.getTarget().getImplementation().getRequest();
+       if (req.status == 200) {
+                   var xml = req.responseXML;
+
+            var finished = xml.getElementsByTagName("finished")[0];
+            var percentCompleted = xml.getElementsByTagName("percent_complete")[0];
+
+            // Check to see if it's even started yet
+            if ((finished == null) && (percentCompleted == null)) {
+                if (!this._monitorRequestFailed) {
+                       // Try refreshing once only to avoid endless loops
+                       this._monitorRequestFailed = true;
+                       qx.client.Timer.once(this._monitorUpload, this, 1000);
+                }
+            }
+            else if (finished == null) {
+                var bytesRead = xml.getElementsByTagName("bytes_read")[0];
+                var contentLength = xml.getElementsByTagName("content_length")[0];
+
+                // Started, get the status of the upload
+                if (percentCompleted != null) {
+                    
+                    if (this._showProgress) {
+                        var progress = percentCompleted.firstChild.data;
+                        this.debug("New Progress " + progress);
+                       this._progressBar.setSelection(progress);
+                    }
+
+                    this.createDispatchDataEvent("upload", false);
+                    
+                    qx.client.Timer.once(this._monitorUpload, this, 1000);
+                }
+                else {
+                    // Finished
+                }
+            }
+        }
+        else {
+            this.debug("HTTP Response NOK: "+ this._req.statusText);
+        }
+       
+    },
+    
+    _onChangeValue : function( evt ) {
+      var wm = org.eclipse.swt.WidgetManager.getInstance();
+      var id = wm.findIdByWidget( this );
+      var req = org.eclipse.swt.Request.getInstance();
+      req.addParameter( id + ".path", evt.getValue() );
+      req.send();
+    },
+    
+    _performUpload : function() {
+      this._uploadFile();
+    },
+    
+    _resetUpload : function() {
+      if (this._progressBar) {
+         this._progressBar.setSelection(0);
+      }
+      if (this._uploadField.isCreated()) {
+        this._uploadField.setValue("");
+      }
+    },
+    
+    /*
+     * This is a workaround as enablement does not work with the base
+     * file upload widgets.
+     * TODO: [sr] disable/enable doesn't work with IE8.
+     */
+    _onEnabled : function( evt ) {
+      qx.ui.core.Widget.flushGlobalQueues();
+
+      if( evt.getValue() ) {
+        this._uploadField._button._input.style.height
+          = this._uploadField.getHeight();        
+      } else {
+        this._uploadField._button._input.style.height = "0px";
+      }
+    },
+    
+    /*
+     * This is a workaround as the underlying file upload takes the focus
+     * despite the hidefocus style settings.
+     */
+    _onFocus : function( evt ) {
+      var input = this._uploadField._button._input;
+      this._uploadField._button._input.onblur = function() {
+        input.onblur = null;
+        input.onfocus = function() { input.blur(), input.onfocus = null };
+      };
+    },
+    
+    // TODO [fappel]: would a property be the better solution?
+    setBrowseButtonText : function( browseButtonText, width ) {
+      this._uploadField._button.setLabel( browseButtonText );
+      this._uploadField._button.setWidth( width );
+    },
+    
+    // TODO [fappel]: would a property be the better solution?
+    setUploadButtonText : function( uploadButtonText, width ) {
+      if( this._showUploadButton ) {
+        this._uploadButton.setLabel( uploadButtonText );
+        this._uploadButton.setWidth( width );
+      }
+    },
+    
+    // 325753: [upload] Styling of text widget border is not applied correctly
+       // https://bugs.eclipse.org/bugs/show_bug.cgi?id=325753
+    addState : function(vState) {
+       // Delegate styles ("rwt_BORDER") to TextField
+       if (this._uploadField && this._uploadField._text) {
+               this._uploadField._text.addState(vState);
+       }
+    },
+    
+    removeState : function(vState) {
+       // Delegate styles ("rwt_BORDER") to TextField
+       if (this._uploadField && this._uploadField._text) {
+               this._uploadField._text.removeState(vState);
+       }
+    }
+    
+  }
+} );
diff --git a/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/UploadAdapter.java b/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/UploadAdapter.java
new file mode 100644 (file)
index 0000000..634f9b2
--- /dev/null
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2002-2006 Innoopract Informationssysteme GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     Innoopract Informationssysteme GmbH - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rwt.widgets;
+
+/**
+ * Listener adaptor with empty implementations of all listener methods.
+ * @author stefan.roeck */
+public class UploadAdapter implements UploadListener {
+
+  public void uploadFinished( final UploadEvent uploadEvent ) {
+  }
+
+  public void uploadInProgress( final UploadEvent uploadEvent ) {
+  }
+
+  public void uploadException( final UploadEvent uploadEvent ) {
+  }
+}
diff --git a/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/UploadEvent.java b/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/UploadEvent.java
new file mode 100644 (file)
index 0000000..56e7532
--- /dev/null
@@ -0,0 +1,150 @@
+/*******************************************************************************
+ * Copyright (c) 2002-2007 Critical Software S.A.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Tiago Rodrigues (Critical Software S.A.) - initial implementation
+ *     Joel Oliveira (Critical Software S.A.) - initial commit
+ ******************************************************************************/
+package org.eclipse.rwt.widgets;
+
+import org.eclipse.rwt.Adaptable;
+import org.eclipse.swt.events.TypedEvent;
+import org.eclipse.swt.widgets.Widget;
+
+/**
+ * Represents an Upload Event.
+ *
+ * @author tjarodrigues
+ * @version $Revision: 1.6 $
+ */
+public class UploadEvent extends TypedEvent {
+  
+  private static final long serialVersionUID = 1L;
+  /**
+   * Hopefully, this isn't occupied by another custom event type
+   */
+  private static final int UPLOAD_FINISHED = 101;
+  private static final int UPLOAD_IN_PROGRESS = 102;
+  private static final int UPLOAD_EXCEPTION = 103;
+  
+  private static final Class LISTENER = UploadListener.class;
+  private final boolean finished;
+  private final int uploadedParcial;
+  private final int uploadedTotal;
+  private final Exception uploadException;
+
+  
+  /**
+   * Returns an exception that occurred during upload during
+   * processing the file on the server side.
+   */
+  public Exception getUploadException() {
+    return uploadException;
+  }
+
+  /**
+   * Checks if the Upload has finished.
+   * 
+   * @return <code>True</code> if the Upload has finished, <code>False</code>
+   *         otherwise.
+   */
+  public final boolean isFinished() {
+    return finished;
+  }
+
+  /**
+   * Gets the partial amount of data uploaded.
+   *
+   * @return The partial amount of data uploaded.
+   */
+  public final int getUploadedParcial() {
+    return this.uploadedParcial;
+  }
+
+  /**
+   * Gets the total file size.
+   *
+   * @return The total file size.
+   */
+  public final int getUploadedTotal() {
+    return this.uploadedTotal;
+  }
+
+  /**
+   * Creates a new instance of the Upload Event.
+   *
+   * @param finished Indicates if the upload is finished.
+   * @param uploadedParcial The partial amount of data uploaded.
+   * @param uploadedTotal The total file size.
+   * @param widget The sender of the event, must not be null
+   */
+  public UploadEvent( final Widget widget,
+                      final boolean finished,
+                      final int uploadedParcial,
+                      final int uploadedTotal )
+  {
+    super( widget, finished
+                           ? UPLOAD_FINISHED
+                           : UPLOAD_IN_PROGRESS );
+    this.finished = finished;
+    this.uploadedParcial = uploadedParcial;
+    this.uploadedTotal = uploadedTotal;
+    this.uploadException = null;
+  }
+  
+  public UploadEvent( final Widget widget, final Exception uploadException ) {
+    super(widget, UPLOAD_EXCEPTION);
+    this.finished = true;
+    this.uploadedParcial = -1;
+    this.uploadedTotal = -1;
+    this.uploadException = uploadException;
+  }
+
+  protected void dispatchToObserver( final Object listener ) {
+    switch( getID() ) {
+      case UPLOAD_IN_PROGRESS:
+        ( ( UploadListener )listener ).uploadInProgress( this );
+      break;
+      case UPLOAD_FINISHED:
+        ( ( UploadListener )listener ).uploadFinished( this );
+      break;
+      case UPLOAD_EXCEPTION:
+        ( ( UploadListener )listener ).uploadException( this );
+      break;
+      default:
+        throw new IllegalStateException( "Invalid event handler type." );
+    }
+  }
+
+  protected Class getListenerType() {
+    return LISTENER;
+  }
+
+  protected boolean allowProcessing() {
+    return true;
+  }
+
+  public static void addListener( final Adaptable adaptable, 
+                                  final UploadListener listener )
+  {
+    addListener( adaptable, LISTENER, listener );
+  }
+
+  public static void removeListener( final Adaptable adaptable, 
+                                     final UploadListener listener )
+  {
+    removeListener( adaptable, LISTENER, listener );
+  }
+  
+  public static boolean hasListener( final Adaptable adaptable ) {
+    return hasListener( adaptable, LISTENER );
+  }
+  
+  public static Object[] getListeners( final Adaptable adaptable ) {
+    return getListener( adaptable, LISTENER );
+  }
+}
diff --git a/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/UploadItem.java b/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/UploadItem.java
new file mode 100644 (file)
index 0000000..650711d
--- /dev/null
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * Copyright (c) 2002-2006 Innoopract Informationssysteme GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     Innoopract Informationssysteme GmbH - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.rwt.widgets;
+
+import java.io.InputStream;
+
+/**
+ * Pojo for which contains a reference to the uploaded file stream and all
+ * available meta information.
+ * 
+ * @author Stefan.Roeck
+ */
+public class UploadItem {
+
+  private final InputStream fileInputStream;
+  private final String contentType;
+  private final String fileName;
+  private final String filePath;
+  private final long fileSize;
+  
+  /**
+   * Creates an UploadItem instance with the given parameters which all can be
+   * null.
+   */
+  public UploadItem( final InputStream fileInputStream,
+                     final String contentType,
+                     final String fileName,
+                     final String filePath,
+                     final long fileSize)
+  {
+    super();
+    this.fileInputStream = fileInputStream;
+    this.fileName = fileName;
+    this.filePath = filePath;
+    this.contentType = contentType;
+    this.fileSize = fileSize;
+  }
+  
+  /**
+   * Returns an inputstream to the uploaded file. Make sure to call
+   * {@link InputStream#close()} if processing the file is finished.    
+   */
+  public InputStream getFileInputStream() {
+    return fileInputStream;
+  }
+  
+  /**
+   * Returns the content type of the last uploaded file as submitted in 
+   * http POST request by the browser. See RFC2616 for possible values.
+   */
+  public String getContentType() {
+    return contentType;
+  }
+
+  
+  /**
+   * Returns the file name of the uploaded file without any path information.
+   */
+  public String getFileName() {
+    return fileName;
+  }
+  
+  /**
+   * Returns the file name plus the local path where this file has been chosen
+   * from. <br/> Note: In Firefox 3 the return value equals
+   * {@link UploadItem#getFileName()}. (Tested with RC1)
+   */
+  public String getFilePath() {
+    return filePath;
+  }
+
+  /**
+   * Returns the size of the File in the {@link UploadItem#getFileInputStream()} thats stored in this UploadItem
+   * . (Tested with RC3)
+   */
+  public long getFileSize() {
+    return fileSize;
+  }
+}
diff --git a/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/UploadListener.java b/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/UploadListener.java
new file mode 100644 (file)
index 0000000..728a6cc
--- /dev/null
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2002-2007 Critical Software S.A.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Tiago Rodrigues (Critical Software S.A.) - initial implementation
+ *     Joel Oliveira (Critical Software S.A.) - initial commit
+ ******************************************************************************/
+package org.eclipse.rwt.widgets;
+
+import java.util.EventListener;
+
+
+/**
+ * Use a UploadListener to get notified when a file upload has 
+ * finished.
+ * 
+ * @author tjarodrigues
+ * @version $Revision: 1.2 $
+ */
+public interface UploadListener extends EventListener{
+
+  /**
+   * Is called, when uploading a file has been finished sucessfully.
+   * @param uploadEvent The Upload Event to be fired. 
+   * {@link UploadEvent#getSource()} returns the upload
+   * widget which triggered the event. All other fields are empty
+   */
+  public void uploadFinished( final UploadEvent uploadEvent );
+  
+  
+  /**
+   * Is called when the upload is in progress. You may use the
+   * {@link UploadEvent} to get details on the progress.
+   */
+  public void uploadInProgress( final UploadEvent uploadEvent );
+
+
+  /**
+   * Signals that an exception has ocurred while receiving the
+   * file to be uploaded. The exception can be retrieved
+   * using {@link UploadEvent#getUploadException()}.
+   */
+  public void uploadException( final UploadEvent uploadEvent );
+}
diff --git a/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/internal/UploadConfiguration.java b/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/internal/UploadConfiguration.java
new file mode 100644 (file)
index 0000000..3587651
--- /dev/null
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2002-2006 Innoopract Informationssysteme GmbH. All rights
+ * reserved. This program and the accompanying materials are made available
+ * under the terms of the Eclipse Public License v1.0 which accompanies this
+ * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html
+ * Contributors: Innoopract Informationssysteme GmbH - initial API and
+ * implementation
+ ******************************************************************************/
+package org.eclipse.rwt.widgets.internal;
+
+import org.eclipse.rwt.widgets.IUploadConfiguration;
+
+public class UploadConfiguration implements IUploadConfiguration {
+
+  private long fileSizeMax = -1;
+  private long sizeMax = -1;
+
+  public synchronized long getFileSizeMax() {
+    return fileSizeMax;
+  }
+
+  public synchronized long getSizeMax() {
+    return sizeMax;
+  }
+
+  public synchronized void setFileMaxSize( final long fileSizeMax ) {
+    this.fileSizeMax = fileSizeMax;
+  }
+
+  public synchronized void setSizeMax( final long sizeMax ) {
+    this.sizeMax = sizeMax;
+  }
+}
diff --git a/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/internal/resource/UploadButtonResource.java b/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/internal/resource/UploadButtonResource.java
new file mode 100644 (file)
index 0000000..d848210
--- /dev/null
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * Copyright (c) 2002-2007 Critical Software S.A.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Tiago Rodrigues (Critical Software S.A.) - initial implementation
+ *     Joel Oliveira (Critical Software S.A.) - initial commit
+ ******************************************************************************/
+package org.eclipse.rwt.widgets.internal.resource;
+
+import org.eclipse.rwt.resources.IResource;
+import org.eclipse.rwt.resources.IResourceManager.RegisterOptions;
+
+/**
+ * Resource definition for "UploadField.js".
+ * 
+ * @author tjarodrigues
+ */
+public class UploadButtonResource implements IResource {
+
+  /**
+   * Retrives the resource Charset.
+   * 
+   * @return Resource <code>Charset</code>.
+   */
+  public final String getCharset() {
+    return "ISO-8859-1";
+  }
+
+  /**
+   * Gets the resource Class Loader.
+   * 
+   * @return Resource <code>ClassLoader</code>.
+   */
+  public final ClassLoader getLoader() {
+    return getClass().getClassLoader();
+  }
+
+  /**
+   * Gets the resource Register Options.
+   * 
+   * @return Resource <code>RegisterOptions</code>
+   */
+  public final RegisterOptions getOptions() {
+    return RegisterOptions.VERSION_AND_COMPRESS;
+  }
+
+  /**
+   * Gets the location of the resource.
+   * 
+   * @return Resource location <code>String</code>.
+   */
+  public final String getLocation() {
+    return "org/eclipse/rwt/widgets/internal/resource/qxcontrib/UploadButton.js";
+  }
+
+  /**
+   * Checks if the resource is a JavaScript library.
+   * 
+   * @return <code>True</code> if the resource is a JavaScript library,
+   *         <code>False</code> otherwise.
+   */
+  public final boolean isJSLibrary() {
+    return true;
+  }
+
+  /**
+   * Checks if the resource is an external library.
+   * 
+   * @return <code>True</code> if the resource is an external library,
+   *         <code>False</code> otherwise.
+   */
+  public final boolean isExternal() {
+    return false;
+  }
+}
diff --git a/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/internal/resource/UploadFieldResource.java b/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/internal/resource/UploadFieldResource.java
new file mode 100644 (file)
index 0000000..bb82f6c
--- /dev/null
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2002-2006 Innoopract Informationssysteme GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     Innoopract Informationssysteme GmbH - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.rwt.widgets.internal.resource;
+
+import org.eclipse.rwt.resources.IResource;
+import org.eclipse.rwt.resources.IResourceManager.RegisterOptions;
+
+
+public class UploadFieldResource implements IResource {
+
+  public String getCharset() {
+    return "ISO-8859-1";
+  }
+
+  public ClassLoader getLoader() {
+    return getClass().getClassLoader();
+  }
+
+  public String getLocation() {
+    return "org/eclipse/rwt/widgets/internal/resource/qxcontrib/UploadField.js";
+  }
+
+  public RegisterOptions getOptions() {
+    return RegisterOptions.VERSION_AND_COMPRESS;
+  }
+
+  public boolean isExternal() {
+    return false;
+  }
+
+  public boolean isJSLibrary() {
+    return true;
+  }
+}
diff --git a/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/internal/resource/UploadFormResource.java b/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/internal/resource/UploadFormResource.java
new file mode 100644 (file)
index 0000000..f2df819
--- /dev/null
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2002-2006 Innoopract Informationssysteme GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     Innoopract Informationssysteme GmbH - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.rwt.widgets.internal.resource;
+
+import org.eclipse.rwt.resources.IResource;
+import org.eclipse.rwt.resources.IResourceManager.RegisterOptions;
+
+
+public class UploadFormResource implements IResource {
+
+  public String getCharset() {
+    return "ISO-8859-1";
+  }
+
+  public ClassLoader getLoader() {
+    return getClass().getClassLoader();
+  }
+
+  public String getLocation() {
+    return "org/eclipse/rwt/widgets/internal/resource/qxcontrib/UploadForm.js";
+  }
+
+  public RegisterOptions getOptions() {
+    return RegisterOptions.VERSION_AND_COMPRESS;
+  }
+
+  public boolean isExternal() {
+    return false;
+  }
+
+  public boolean isJSLibrary() {
+    return true;
+  }
+}
diff --git a/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/internal/resource/UploadResource.java b/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/internal/resource/UploadResource.java
new file mode 100644 (file)
index 0000000..a3a7385
--- /dev/null
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * Copyright (c) 2002-2007 Critical Software S.A.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Tiago Rodrigues (Critical Software S.A.) - initial implementation
+ *     Joel Oliveira (Critical Software S.A.) - initial commit
+ ******************************************************************************/
+package org.eclipse.rwt.widgets.internal.resource;
+
+import org.eclipse.rwt.resources.IResource;
+import org.eclipse.rwt.resources.IResourceManager.RegisterOptions;
+
+/**
+ * Resource definition for "Upload.js".
+ * 
+ * @author tjarodrigues
+ */
+public class UploadResource implements IResource {
+
+  /**
+   * Retrives the resource Charset.
+   * 
+   * @return Resource <code>Charset</code>.
+   */
+  public final String getCharset() {
+    return "ISO-8859-1";
+  }
+
+  /**
+   * Gets the resource Class Loader.
+   * 
+   * @return Resource <code>ClassLoader</code>.
+   */
+  public final ClassLoader getLoader() {
+    return this.getClass().getClassLoader();
+  }
+
+  /**
+   * Gets the resource Register Options.
+   * 
+   * @return Resource <code>RegisterOptions</code>
+   */
+  public final RegisterOptions getOptions() {
+    return RegisterOptions.VERSION_AND_COMPRESS;
+  }
+
+  /**
+   * Gets the location of the resource.
+   * 
+   * @return Resource location <code>String</code>.
+   */
+  public final String getLocation() {
+    return "org/eclipse/rwt/widgets/Upload.js";
+  }
+
+  /**
+   * Checks if the resource is a JavaScript library.
+   * 
+   * @return <code>True</code> if the resource is a JavaScript library,
+   *         <code>False</code> otherwise.
+   */
+  public final boolean isJSLibrary() {
+    return true;
+  }
+
+  /**
+   * Checks if the resource is an external library.
+   * 
+   * @return <code>True</code> if the resource is an external library,
+   *         <code>False</code> otherwise.
+   */
+  public final boolean isExternal() {
+    return false;
+  }
+}
diff --git a/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/internal/resource/qxcontrib/UploadButton.js b/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/internal/resource/qxcontrib/UploadButton.js
new file mode 100644 (file)
index 0000000..e9c70e4
--- /dev/null
@@ -0,0 +1,270 @@
+/* ************************************************************************
+
+   qooxdoo - the new era of web development
+
+   http://qooxdoo.org
+
+   Copyright:
+     2007 Visionet GmbH, http://www.visionet.de
+
+   License:
+     LGPL: http://www.gnu.org/licenses/lgpl.html
+     EPL: http://www.eclipse.org/org/documents/epl-v10.php
+     See the LICENSE file in the project's top-level directory for details.
+
+   Authors:
+     * Dietrich Streifert (level420)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(uploadwidget_ui_io)
+
+************************************************************************ */
+
+/**
+ * An upload button which allows selection of a file through the browser fileselector.
+ *
+ */
+qx.Class.define("uploadwidget.UploadButton",
+{
+  extend : qx.ui.form.Button,
+  
+  /*
+  *****************************************************************************
+     CONSTRUCTOR
+  *****************************************************************************
+  */
+
+  construct : function(name, text, icon, iconWidth, iconHeight, flash)
+  {
+    this.base(arguments, text, icon, iconWidth, iconHeight, flash);
+    // This state is needed for proper button CSS themeing
+    this.addState( "rwt_PUSH" );
+    this.setAppearance( "button" );
+    if(name) {
+      this.setName(name);
+    }
+
+  },
+  
+
+  /*
+  *****************************************************************************
+     PROPERTIES
+  *****************************************************************************
+  */
+
+  properties :
+  {
+    /**
+     * The name which is assigned to the form
+     */
+    name :
+    {
+      check : "String",
+      init : "",
+      apply : "_applyName"
+    },
+
+    /**
+     * The value which is assigned to the form
+     */
+    value :
+    {
+      check : "String",
+      init : "",
+      apply : "_applyValue",
+      event : "changeValue"
+    }
+  }, 
+  
+  /*
+  *****************************************************************************
+     MEMBERS
+  *****************************************************************************
+  */
+
+  members :
+  {
+    /*
+    ---------------------------------------------------------------------------
+      MODIFIERS
+    ---------------------------------------------------------------------------
+    */
+
+    /**
+     * after the button element is present create the input file tag
+     * 
+     * @param value {Object} new dom element
+     * @param old {Object} old one
+     * @type member
+     * @return {void}
+     */
+    _applyElement : function (value, old)
+    {
+      this.base(arguments, value, old);
+      this._createInputFileTag(value);
+    },
+
+
+    /**
+     * Modifies the value property of the hidden input type=file element.
+     * Only an empty string is accepted for clearing out the value of the
+     * selected file.
+     * 
+     * As a special case for IE the hidden input element is recreated because
+     * setting the value is generally not allowed in IE.
+     *
+     * @type member
+     * @param value {var} Current value
+     * @param old {var} Previous value
+     */
+    _applyValue : function(value, old) {
+      if(this._valueInputOnChange) {
+        delete this._valueInputOnChange;
+      }
+      else {
+        if (!value || value == '') {
+          if (qx.core.Variant.isSet("qx.client", "mshtml")) {
+            this._createInputFileTag(this.getElement());
+          }
+          else {
+            this._input.value = '';
+          }
+        }
+        else {
+          throw new Error("Unable to set value to non null or non empty!");
+        }
+      }
+    },
+
+
+    /**
+     * Modifies the name property of the hidden input type=file element.
+     *
+     * @type member
+     * @param value {var} Current value
+     * @param old {var} Previous value
+     */
+    _applyName : function(value, old) {
+      if(this._input) {
+        this._input.name = propValue;
+      }
+    },
+
+
+    /**
+     * Apply the enabled property.
+     *
+     * @type member
+     * @param value {var} Current value
+     * @param old {var} Previous value
+     */
+    _applyEnabled : function(value, old)
+    {
+      if (this._input) {
+        this._input.disabled = value===false;
+      }
+
+      return this.base(arguments, value, old);
+    },
+
+    /*
+    ---------------------------------------------------------------------------
+      EVENT-HANDLER
+    ---------------------------------------------------------------------------
+    */
+    
+    /**
+     * Create an input type=file element, and set the onchange event handler which
+     * fires if the user selected a file with the fileselector.
+     *
+     * @type member
+     * @param e {Event|null} appear event
+     * @return {void}
+     */
+    _createInputFileTag : function(elem)
+    {
+      if(this._input)
+      {
+        this._input.name += "_tmp_";
+        if (this._input.parentNode) {
+               this._input.parentNode.removeChild(this._input);
+        }
+        this._input = null;
+      }
+
+      var input  = this._input = document.createElement("input");
+      input.type = "file";
+      input.name = this.getName();
+      input.size = "1"; // make the text area as small as possible
+      input.style.position  = "absolute";
+      input.style.top          = "-2px"; // make sure to cover the whole area
+      input.style.left      = "-100px";
+      input.style.height    = "27px";
+      input.style.fontSize  = "35px"; // previous value 60 was to small for some systems (depends on used font-family)
+      var clipRight = 300 + this.getWidthValue(); //use variable to avoid string concatenation instead of adding
+      input.style.clip      = "rect(auto, " + clipRight + "px, auto, 100px)";
+      input.style.zIndex    = "100";
+      input.style.cursor    = "pointer";
+      input.style.filter    = "alpha(opacity=0)";
+      input.style.opacity   = "0";
+      input.style.MozOutlinestyle   = "none";
+      input.style.hidefocus         = "true";
+      input.disabled        = this.getEnabled() === false;
+
+      var _this = this;
+      input.onchange = function(ev) { return _this._onChange(ev); };
+
+      elem.appendChild(input);
+    },
+
+
+    /**
+     * Handle the onchange event of the hidden input type=file element
+     *
+     * @type member
+     * @param e {Event} TODOC
+     * @return {void}
+     */
+    _onChange : function(e) {
+      // IE8 returns sth like "C:\fakepath\..." which should not be displayed.
+      // Cut off everyhting before the "\", like Firefox does automatically, to have
+      // an identical behaviour in all browsers.
+      var inputStr = this._input.value;
+      if (inputStr) {
+        if (inputStr.indexOf("\\") != -1) {
+            inputStr = inputStr.substr(inputStr.lastIndexOf("\\") + 1);
+        } else if (inputStr.indexOf("/") != -1) {
+            inputStr = inputStr.substr(inputStr.lastIndexOf("/") + 1);
+        }            
+        
+        this._valueInputOnChange = true;
+           this.setValue(inputStr);
+      }
+    }
+
+  },
+
+
+  /*
+  *****************************************************************************
+     DESTRUCTOR
+  *****************************************************************************
+  */
+
+  destruct : function()
+  {
+    if(this._input) {
+      if (this._input.parentNode) {
+         this._input.parentNode.removeChild(this._input);
+      }          
+      this._input.onchange = null;
+      this._input = null;
+    } 
+  }
+
+});
diff --git a/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/internal/resource/qxcontrib/UploadField.js b/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/internal/resource/qxcontrib/UploadField.js
new file mode 100644 (file)
index 0000000..8043400
--- /dev/null
@@ -0,0 +1,209 @@
+/* ************************************************************************
+
+   qooxdoo - the new era of web development
+
+   http://qooxdoo.org
+
+   Copyright:
+     2007 Visionet GmbH, http://www.visionet.de
+
+   License:
+     LGPL: http://www.gnu.org/licenses/lgpl.html
+     EPL: http://www.eclipse.org/org/documents/epl-v10.php
+     See the LICENSE file in the project's top-level directory for details.
+
+   Authors:
+     * Dietrich Streifert (level420)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(uploadwidget_ui_io)
+
+************************************************************************ */
+
+/**
+ * UploadField: A textfield which holds the filename of the file which
+ * should be uploaded and a button which allows selecting the file via the native
+ * file selector 
+ *
+ */
+qx.Class.define("uploadwidget.UploadField",
+{
+  extend : qx.ui.layout.BoxLayout,
+
+  /*
+  *****************************************************************************
+     CONSTRUCTOR
+  *****************************************************************************
+  */
+
+  construct : function(name, text, icon, iconHeight, flash)
+  {
+    this.base(arguments);
+    
+       if(name) {
+      this.setName(name);
+    }
+
+    this.initHeight();
+    this.initOverflow();
+
+
+       this._text = new qx.ui.form.TextField();
+       this._text.set({readOnly:true,left:0,marginTop:0,paddingTop:0,width:"1*"});
+       this._text.setAppearance( "upload-field" );
+       this.add(this._text);
+
+       this._button = new uploadwidget.UploadButton(this.getName(), text, icon, iconHeight, flash);
+       this._button.set({right:0});
+    this._button.addEventListener("changeValue", this._onChangeValue, this);
+       this.add(this._button);
+  },
+
+  /*
+  *****************************************************************************
+     PROPERTIES
+  *****************************************************************************
+  */
+
+  properties :
+  {
+    /**
+     * The name which is assigned to the form
+     */
+    name :
+    {
+      check : "String",
+      init  : "",
+      apply : "_applyName"
+    },
+
+    /**
+     * The value which is assigned to the form
+     */
+    value :
+    {
+      check : "String",
+      init : "",
+      apply : "_applyValue",
+      event : "changeValue"
+    },
+    
+    /**
+     * refine the initial value of height to auto
+     */
+    height:
+    {
+      refine : true,
+      init   : "auto"
+    },
+    
+    /**
+     * refine the initial value of overflow to hidden
+     */
+    overflow :
+    {
+      refine : true,
+      init   : "hidden"
+    },
+    
+    /**
+     * refine the initial value of spacing to 4
+     */
+    spacing :
+    {
+      refine : true,
+      init   : 3
+    }
+  }, 
+
+  /*
+  *****************************************************************************
+     MEMBERS
+  *****************************************************************************
+  */
+
+  members :
+  {
+    /*
+    ------------------------------------------------------------------------------------
+      Instance variables
+    ------------------------------------------------------------------------------------
+    */
+
+    _value : "",
+
+
+    /*
+    ---------------------------------------------------------------------------
+      MODIFIERS
+    ---------------------------------------------------------------------------
+    */
+    
+    /**
+     * Value modifier. Sets the value of both the text field and
+     * the UploadButton. The setValue modifier of UploadButton
+     * throws an exception if the value is not an empty string.
+     *
+     * @type member
+     * @param value {var} Current value
+     * @param old {var} Previous value
+     */
+    _applyValue : function(value, old) {
+      this._button.setValue(value);
+      this._text.setValue(value);
+    },
+
+
+    /**
+     * Upload parameter value modifier. Sets the name attribute of the
+     * the hidden input type=file element in UploadButton which should.
+     * This name is the form submission parameter name.
+     *
+     * @type member
+     * @param value {var} Current value
+     * @param old {var} Previous value
+     */
+    _applyName : function(value, old) {
+      if(this._button) {
+        this._button.setName(value);
+      }
+    },
+
+
+    
+    /*
+    ---------------------------------------------------------------------------
+      EVENT HANDLER
+    ---------------------------------------------------------------------------
+    */
+    
+    /**
+     * If the user select a file by clicking the button, the value of
+     * the input type=file tag of the UploadButton changes and
+     * the text field is set with the value of the selected filename.
+     *
+     * @type member
+     * @param e {Event} change value event data
+     * @return {void}
+     */
+    _onChangeValue : function(e) {
+      var value = e.getValue();
+      this._text.setValue(value);
+      this.setValue(value);
+    }
+  },    
+
+
+  /*
+  *****************************************************************************
+     DESTRUCTOR
+  *****************************************************************************
+  */
+  destruct : function()
+  {
+    this._disposeObjects("_button", "_text");
+  }
+});  
diff --git a/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/internal/resource/qxcontrib/UploadForm.js b/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/internal/resource/qxcontrib/UploadForm.js
new file mode 100644 (file)
index 0000000..b967aa6
--- /dev/null
@@ -0,0 +1,573 @@
+/* ************************************************************************
+
+   qooxdoo - the new era of web development
+
+   http://qooxdoo.org
+
+   Copyright:
+     2007 Visionet GmbH, http://www.visionet.de
+
+   License:
+     LGPL: http://www.gnu.org/licenses/lgpl.html
+     EPL: http://www.eclipse.org/org/documents/epl-v10.php
+     See the LICENSE file in the project's top-level directory for details.
+
+   Authors:
+     * Dietrich Streifert (level420)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(uploadwidget_ui_io)
+#require(qx.xml.Document)
+
+************************************************************************ */
+
+/**
+ * An upload widget implementation capable of holding multiple upload buttons
+ * and upload fields.
+ * 
+ * Each upload form creates an iframe which is used as a target for form submit.
+ * 
+ *
+ */
+qx.Class.define("uploadwidget.UploadForm",
+{
+  extend : qx.ui.layout.CanvasLayout,
+
+  /*
+  *****************************************************************************
+     CONSTRUCTOR
+  *****************************************************************************
+  */
+
+  /**
+   * @param name {String} form name ({@link #name}).
+   * @param url {String} url for form submission ({@link #url}).
+   * @param encoding {String} encoding for from submission. This is an instantiation only parameter and defaults to multipart/form-data
+   */
+  construct : function(name, url, encoding)
+  {
+    this.base(arguments);
+
+    // Apply initial values
+    if(name) {
+      this.setName(name);
+    }
+    
+    if(url) {
+      this.setUrl(url);
+    }
+
+    this.setHtmlProperty("encoding", encoding || "multipart/form-data");
+
+    // Initialize Properties
+    this.initHeight();
+    this.initWidth();
+    this.initSelectable();
+    this.initMethod();
+
+
+    // Initialize Variables
+    this._parameters = {};
+    this._hidden = {};
+
+    // create a hidden iframe which is used as form submission target
+    this._createIFrameTarget();
+  },
+
+
+  /*
+  *****************************************************************************
+     EVENTS
+  *****************************************************************************
+  */
+
+  events:
+  {
+    "sending"    : "qx.event.type.Event",
+    "completed"  : "qx.event.type.Event"
+  },
+
+
+  /*
+  *****************************************************************************
+     PROPERTIES
+  *****************************************************************************
+  */
+
+  properties :
+  {
+    /**
+     * The name which is assigned to the form
+     */
+    name :
+    {
+      check    : "String",
+      init     : "",
+      apply    : "_applyName"
+    },
+
+    /**
+     * The url which is used for form submission.
+     */
+    url :
+    {
+      check    : "String",
+      init     : "",
+      apply    : "_applyUrl"
+    },
+
+    /**
+     * The target which is used for form submission.
+     */
+    target :
+    {
+      check    : "String",
+      init     : "",
+      apply    : "_applyTarget"
+    },
+
+    /**
+     * Determines what type of request to issue (GET or POST).
+     */
+    method :
+    {
+      check : [ qx.net.Http.METHOD_GET, qx.net.Http.METHOD_POST ],
+      init  : qx.net.Http.METHOD_POST,
+      apply : "_applyMethod"
+    },
+
+    /**
+     * refine the initial value of height to auto
+     */
+    height:
+    {
+      refine : true,
+      init   : "auto"
+    },
+
+    /**
+     * refine the initial value of width to auto
+     */
+    width:
+    {
+      refine : true,
+      init   : "auto"
+    },
+
+    /**
+     * refine the initial value of selectable to true
+     */
+    selectable :
+    {
+      refine : true,
+      init   : true
+    }
+  },
+  
+
+  /*
+  *****************************************************************************
+     MEMBERS
+  *****************************************************************************
+  */
+
+  members :
+  {
+
+
+    /*
+    ---------------------------------------------------------------------------
+      APPLY ROUTINES
+    ---------------------------------------------------------------------------
+    */
+
+    _applyName : function(value, old) {
+      this.setHtmlProperty("name", value);
+    },
+    
+    _applyUrl : function(value, old) {
+      this.setHtmlProperty("action", value);
+    },
+
+    _applyTarget : function(value, old) {
+      this.setHtmlProperty("target", value);
+    },
+
+    _applyMethod : function(value, old) {
+      this.setHtmlProperty("method", value);
+    },
+    
+    
+    /*
+    ---------------------------------------------------------------------------
+      UTILITIES
+    ---------------------------------------------------------------------------
+    */
+
+    /**
+     * Create a hidden iframe which is used as target for the form submission.
+     * Don't need a src attribute, if it was set to javascript:void we get an insecure
+     * objects error in IE.
+     *
+     * @type member
+     * @return {void}
+     */
+    _createIFrameTarget : function()
+    {
+      var frameName = "frame_" + (new Date).valueOf();
+
+      if (qx.core.Variant.isSet("qx.client", "mshtml"))
+      {
+        this._iframeNode = document.createElement('<iframe name="' + frameName + '"></iframe>');
+      } else {
+        this._iframeNode = document.createElement("iframe");
+      }
+
+      this._iframeNode.id = this._iframeNode.name = frameName;
+      this._iframeNode.style.display = "none";
+      this.setTarget(frameName);
+
+      document.body.appendChild(this._iframeNode);
+
+      this._iframeNode.onload = qx.lang.Function.bind(this._onLoad, this);
+      this._iframeNode.onreadystatechange = qx.lang.Function.bind(this._onReadyStateChange, this);
+    },
+    
+    
+    /**
+     * Create an empty form widget. IE is not able to change the enctype
+     * after element creation, so the enctype is set by using a skeleton
+     * form tag as parameter for createElement.
+     *
+     * @type member
+     * @return {void}
+     */
+    _createElementImpl : function() {
+      var tagName;
+      if (qx.core.Variant.isSet("qx.client", "mshtml")) {
+        tagName ='<form enctype="' + this.getHtmlProperty("encoding") + '"></form>';
+      } else {
+        tagName = 'form';
+      }
+      
+      this.setElement(this.getTopLevelWidget().getDocumentElement().createElement(tagName));
+    },
+
+
+    /**
+     * Add parameters as hidden fields to the form.
+     *
+     * @type member
+     * @return {object}
+     */
+    _addFormParameters : function() {
+      var form = this.getElement();
+      var parameters = this.getParameters();
+
+      for (var id in parameters) {
+        form.appendChild(this._hidden[id]);
+      }
+    },
+
+
+    /**
+     * Create an input element of type hidden with the 
+     * name ({@link #name}) and value ({@link #value})
+     *
+     * @type member
+     * @param name {String} name attribute of the created element ({@link #name}).
+     * @param value {String} value attribute of the created element ({@link #value}).
+     * @return {void}
+     */
+    _createHiddenFormField : function(name,value) {
+      var hvalue = document.createElement("input");
+      hvalue.type = "hidden";
+      hvalue.name = name;
+      hvalue.value = value;
+    
+      return hvalue;
+    },
+
+
+    /**
+     * Set a request parameter which is stored as an input type=hidden.
+     * 
+     * @param id String identifier of the parameter to add.
+     * @param value String Value of parameter.
+     * @return {void}
+     */
+    setParameter : function(id, value) {
+      this._parameters[id] = value;
+      if(this._hidden[id] && this._hidden[id].name) {
+        this._hidden[id].value = value;
+      }
+      else {
+        this._hidden[id] = this._createHiddenFormField(id, value);
+      }
+    },
+
+
+    /**
+     * Remove a parameter from the request.
+     * 
+     * @param id String identifier of the parameter to remove.
+     * @return {void}
+     */
+    removeParameter : function(id) {
+      delete this._parameters[id];
+      if(this._hidden[id] && this._hidden[id].parentNode) {
+        this._hidden[id].parentNode.removeChild(this._hidden[id]);
+      }
+      delete this._hidden[id];
+    },
+
+
+    /**
+     * Get a parameter in the request.
+     * 
+     * @param id String identifier of the parameter to get.
+     * @return {String}
+     */
+    getParameter : function(id) {
+      return this._parameters[id] || null;
+    },
+
+    
+    /**
+     * Returns the array containg all parameters for the request.
+     * 
+     * @return {Array}
+     */
+    getParameters : function() {
+      return this._parameters;
+    },
+
+
+    /**
+     * Send the form via the submit method. Target defaults to the
+     * self created iframe.
+     * 
+     * @return {void}
+     */
+    send :  function() {
+      var form = this.getElement();
+      if(form) {
+        this._addFormParameters();
+
+        form.submit();
+
+        this._isSent = true;
+        this.createDispatchEvent("sending");
+      }
+      else {
+        throw new Error("Form element not created! Unable to call form submit!");
+      }
+    },
+
+
+
+    /*
+    ---------------------------------------------------------------------------
+      FRAME UTILITIES
+    ---------------------------------------------------------------------------
+    */
+    
+    /**
+     * Get the DOM window object of the target iframe.
+     *
+     * @type member
+     * @return {DOMWindow} The DOM window object of the iframe.
+     */
+    getIframeWindow : function() {
+      return qx.html.Iframe.getWindow(this._iframeNode);
+    },
+
+    
+    /**
+     * Get the DOM document object of the target iframe.
+     *
+     * @type member
+     * @return {DOMDocument} The DOM document object of the iframe.
+     */
+    getIframeDocument : function() {
+      return qx.html.Iframe.getDocument(this._iframeNode);
+    },
+    
+
+    /**
+     * Get the HTML body element of the target iframe.
+     *
+     * @type member
+     * @return {Element} The DOM node of the <code>body</code> element of the iframe.
+     */
+    getIframeBody : function() {
+      return qx.html.Iframe.getBody(this._iframeNode);
+    },
+
+    
+    /**
+     * Get the target iframe Element.
+     *
+     * @type member
+     * @return {Element} The DOM element of the iframe.
+     */
+    getIframeNode : function() {
+      return this._iframeNode;
+    },
+
+
+
+    /*
+    ---------------------------------------------------------------------------
+      RESPONSE DATA SUPPORT
+    ---------------------------------------------------------------------------
+    */
+    
+    /**
+     * Get the text content of the target iframe. 
+     *
+     * @type member
+     * @return {String} The text response of the submit.
+     */
+    getIframeTextContent : function() {
+      var vBody = this.getIframeBody();
+    
+      if (!vBody) {
+        return null;
+      }
+    
+      // Mshtml returns the content inside a PRE
+      // element if we use plain text
+      if (vBody.firstChild && (vBody.firstChild.tagName == "PRE" || vBody.firstChild.tagName == "pre"))
+      {
+        return vBody.firstChild.innerHTML;
+      }
+      else
+      {
+        return vBody.innerHTML;
+      }
+    },
+    
+
+    /**
+     * Get the HTML content of the target iframe. 
+     *
+     * @type member
+     * @return {String} The html response of the submit.
+     */
+    getIframeHtmlContent : function() {
+      var vBody = this.getIframeBody();
+      return vBody ? vBody.innerHTML : null;
+    },
+    
+
+    /**
+     * Get the XML content of the target iframe. 
+     * 
+     * This is a hack for now because I didn't find a way
+     * to send XML via the iframe response.
+     * 
+     * In the resulting text all occurences of the &lt;
+     * and &gt; entities are replaces by < and > and
+     * the Text is then parsed into a XML-Document instance.
+     *
+     * @type member
+     * @return {Document} The XML response of the submit.
+     */
+    getIframeXmlContent : function() {
+      var responsetext = this.getIframeTextContent();
+    
+      if(!responsetext || responsetext.length == 0) {
+        return null;
+      }
+    
+      var xmlContent = null;
+      var newText = responsetext.replace(/&lt;/g,"<");
+      newText = newText.replace(/&gt;/g, ">");
+    
+      try {
+        xmlContent = qx.xml.Document.fromString(newText);
+      }
+      catch(ex) {};
+    
+      return xmlContent;
+    },
+
+
+
+    /*
+    ---------------------------------------------------------------------------
+      EVENT HANDLER
+    ---------------------------------------------------------------------------
+    */
+    
+    /**
+     * Catch the onreadystatechange event of the target iframe.
+     *
+     * @type member
+     * @param e {Event}
+     * @return {void}
+     */
+    _onReadyStateChange : function(e) {
+      if (this.getIframeNode().readyState == "complete" && this._isSent) {
+        this.createDispatchEvent("completed");
+        delete this._isSent;
+      }
+    },
+
+    
+    /**
+     * Catch the onload event of the target iframe
+     *
+     * @type member
+     * @param e {Event}
+     * @return {void}
+     */
+    _onLoad : function(e) {
+      if(this._isSent) {
+        this.createDispatchEvent("completed");
+        delete this._isSent;
+      }
+    }
+  },
+
+  /*
+  *****************************************************************************
+     DESTRUCTOR
+  *****************************************************************************
+  */
+
+  destruct : function()
+  {
+    if (this._iframeNode)
+    {
+      try
+      {
+        document.body.removeChild(this._iframeNode);
+        this._iframeNode.onreadystatechange = null;
+        this._iframeNode.onload = null;
+        this._iframeNode = null;
+      }
+      catch (exc)
+      {
+        this.warn("can't remove iframe node from dom.");
+      }
+    }
+  
+    this._parameters = null;
+  
+    for (var id in this._hidden)
+    {
+      if(this._hidden[id] && this._hidden[id].parentNode)
+      {
+        this._hidden[id].parentNode.removeChild(this._hidden[id]);
+      }
+    }
+    
+    this._hidden = null;
+  }
+});  
+
diff --git a/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/internal/uploadkit/IUploadAdapter.java b/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/internal/uploadkit/IUploadAdapter.java
new file mode 100644 (file)
index 0000000..f33945c
--- /dev/null
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2002-2006 Innoopract Informationssysteme GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     Innoopract Informationssysteme GmbH - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.rwt.widgets.internal.uploadkit;
+
+import org.eclipse.rwt.widgets.upload.servlet.FileUploadStorageItem;
+
+public interface IUploadAdapter {
+  boolean performUpload();
+  int getFlags();
+  void setPath( final String path );
+  void setLastFileUploaded( final String lastFileUploaded );
+  String getServletPath();
+  boolean isResetUpload();
+  void setResetUpload(boolean resetUpload);
+  public long getBytesRead();
+  public long getContentLength();
+  FileUploadStorageItem getStorageItem();
+}
diff --git a/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/internal/uploadkit/Upload.appearances.js b/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/internal/uploadkit/Upload.appearances.js
new file mode 100644 (file)
index 0000000..e453865
--- /dev/null
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2002-2007 Critical Software S.A.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Tiago Rodrigues (Critical Software S.A.) - initial implementation
+ *     Joel Oliveira (Critical Software S.A.) - initial commit
+ ******************************************************************************/
+appearances = {
+// BEGIN TEMPLATE //
+    
+    /*
+    ---------------------------------------------------------------------------
+      UPLOAD
+    ---------------------------------------------------------------------------
+    */
+
+    "upload-field" : {
+      style : function( states ) {
+        var tv = new org.eclipse.swt.theme.ThemeValues( states );
+        return {
+          border : tv.getCssBorder( "Text", "border" ),
+          font : tv.getCssFont( "Text", "font" ),
+          padding : tv.getCssBoxDimensions( "Text", "padding" ),
+          textColor : tv.getCssColor( "Text", "color" ),
+          backgroundColor : tv.getCssColor( "Text", "background-color" )
+        };
+      }
+    }
+    
+// END TEMPLATE //
+};
diff --git a/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/internal/uploadkit/UploadLCA.java b/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/internal/uploadkit/UploadLCA.java
new file mode 100644 (file)
index 0000000..55a0e53
--- /dev/null
@@ -0,0 +1,182 @@
+/*******************************************************************************
+ * Copyright (c) 2002-2007 Critical Software S.A. All rights reserved. This
+ * program and the accompanying materials are made available under the terms of
+ * the Eclipse Public License v1.0 which accompanies this distribution, and is
+ * available at http://www.eclipse.org/legal/epl-v10.html Contributors: Tiago
+ * Rodrigues (Critical Software S.A.) - initial implementation Joel Oliveira
+ * (Critical Software S.A.) - initial commit
+ ******************************************************************************/
+package org.eclipse.rwt.widgets.internal.uploadkit;
+
+import java.io.IOException;
+
+import org.eclipse.rwt.graphics.Graphics;
+import org.eclipse.rwt.lifecycle.*;
+import org.eclipse.rwt.widgets.Upload;
+import org.eclipse.rwt.widgets.UploadEvent;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Widget;
+
+/**
+ * Class that interfaces between the Java and the JavaScript.
+ * 
+ * @author tjarodrigues
+ */
+public class UploadLCA extends AbstractWidgetLCA {
+  private static final String PROP_LASTFILEUPLOADED = "lastFileUploaded";
+
+  private static final String JS_PROP_LASTFILEUPLOADED = "lastFileUploaded";
+  private static final String JS_PROP_BROWSE_BUTTON_TEXT = "browseButtonText";
+  private static final String JS_PROP_UPLOAD_BUTTON_TEXT = "uploadButtonText";
+
+  /**
+   * Preserves the property values between the Java and the JavaScript.
+   * 
+   * @param widget The <code>Widget</code>.
+   */
+  public final void preserveValues( final Widget widget ) {
+    Upload upload = ( Upload )widget;
+    ControlLCAUtil.preserveValues( upload );
+    IWidgetAdapter adapter = WidgetUtil.getAdapter( widget );
+    adapter.preserve( PROP_LASTFILEUPLOADED, upload.getLastFileUploaded() );
+    adapter.preserve( JS_PROP_BROWSE_BUTTON_TEXT, upload.getBrowseButtonText() );
+    adapter.preserve( JS_PROP_UPLOAD_BUTTON_TEXT, upload.getUploadButtonText() );
+  }
+
+  /**
+   * Reads data from the <code>Widget</code>.
+   * 
+   * @param widget The <code>Widget</code>.
+   */
+  public final void readData( final Widget widget ) {
+    final Upload upload = ( Upload )widget;
+    String lastFileUploaded = WidgetLCAUtil.readPropertyValue( upload,
+                                                               "lastFileUploaded" );
+    String path = WidgetLCAUtil.readPropertyValue( upload, "path" );
+    final IUploadAdapter adapter = getAdapter( upload );
+    adapter.setPath( path );
+    adapter.setLastFileUploaded( lastFileUploaded );
+    final String finished = WidgetLCAUtil.readPropertyValue( upload, "finished" );
+    
+    // TODO: [sr] handle if long
+    final int uploadPartial = ( int )adapter.getBytesRead();
+    final int uploadTotal = ( int )adapter.getContentLength();
+    
+    if( finished != null ) 
+    {
+      // Check if there was any exception during upload
+      final Exception uploadException = adapter.getStorageItem().getException();
+      
+      // At the moment, the event must be fire directly via the ProcessActionRunner
+      // because delayed execution doesn't work at the moment for custom events.
+      // If this changes one day, processEvent() can be called directly.
+      ProcessActionRunner.add( new Runnable() {
+        
+        public void run() {
+          final UploadEvent evt;
+          if (uploadException != null) {
+            evt = new UploadEvent(widget, uploadException);
+          } else {
+            evt = new UploadEvent( upload, Boolean.valueOf( finished )
+              .booleanValue(), uploadPartial, uploadTotal );            
+          }
+          evt.processEvent();
+
+        }
+      });
+    }
+  }
+
+  /**
+   * Creates the initial <code>Widget</code> rendering.
+   * 
+   * @param widget The <code>Widget</code>.
+   * @throws IOException If the <code>Widget</code> JavaScript is not found.
+   */
+  public final void renderInitialization( final Widget widget )
+    throws IOException
+  {
+    final JSWriter writer = JSWriter.getWriterFor( widget );
+    final Upload upload = ( Upload )widget;
+    
+    final String servletPath = getAdapter( upload ).getServletPath();
+    
+    writer.newWidget( "org.eclipse.rwt.widgets.Upload", new Object[] {
+      servletPath, 
+      new Integer( getAdapter( upload ).getFlags() ) 
+    } );
+    writer.set( "appearance", "composite" );
+    writer.set( "overflow", "hidden" );
+    ControlLCAUtil.writeStyleFlags( ( Upload )widget );
+  }
+
+  /**
+   * Renders the <code>Widget</code> changes in the JavaScript.
+   * 
+   * @param widget The <code>Widget</code>.
+   * @throws IOException If the <code>Widget</code> JavaScript is not found.
+   */
+  public final void renderChanges( final Widget widget ) throws IOException {
+    final Upload upload = ( Upload )widget;
+    ControlLCAUtil.writeChanges( upload );
+    final JSWriter writer = JSWriter.getWriterFor( widget );
+    IUploadAdapter uploadAdapter = getAdapter( upload );
+    
+    ////////////////////////////////////////////////////////////////////////////
+    // TODO [fappel]: check whether this is useful and if so, whether preserve
+    //                works properly
+    final String lastFileUploaded = upload.getLastFileUploaded();
+    writer.set( PROP_LASTFILEUPLOADED,
+                JS_PROP_LASTFILEUPLOADED,
+                lastFileUploaded );
+    ////////////////////////////////////////////////////////////////////////////
+    
+    
+    IWidgetAdapter adapter = WidgetUtil.getAdapter( widget );
+    boolean changed;
+    
+    changed = !adapter.isInitialized()
+      || WidgetLCAUtil.hasChanged( widget, JS_PROP_BROWSE_BUTTON_TEXT, upload.getBrowseButtonText() );
+    if( changed ) {
+      final Point textExtent = Graphics.stringExtent( upload.getFont(), upload.getBrowseButtonText());
+      final Object textWidth = new Integer( textExtent.x + 7);
+      writer.set( JS_PROP_BROWSE_BUTTON_TEXT, new Object[] {upload.getBrowseButtonText(), textWidth});
+    }
+    
+    if( ( uploadAdapter.getFlags() & Upload.SHOW_UPLOAD_BUTTON ) > 0 ) {
+      changed = !adapter.isInitialized()
+      || WidgetLCAUtil.hasChanged( widget, JS_PROP_UPLOAD_BUTTON_TEXT, upload.getUploadButtonText() );
+    
+      if( changed ) {
+        final Point textExtent = Graphics.stringExtent( upload.getFont(), upload.getUploadButtonText());
+        final Object textWidth = new Integer( textExtent.x + 7);
+        writer.set( JS_PROP_UPLOAD_BUTTON_TEXT, new Object[] {upload.getUploadButtonText(), textWidth});
+      }
+      
+    }
+    
+    if( uploadAdapter.performUpload() ) {
+      writer.call( upload, "_performUpload", null );
+    }
+    
+    if( uploadAdapter.isResetUpload() ) {
+      writer.call( upload, "_resetUpload", null );
+      uploadAdapter.setResetUpload( false );
+    }
+  }
+
+  /**
+   * Renders the <code>Widget</code> dispose in the JavaScript.
+   * 
+   * @param widget The <code>Widget</code>.
+   * @throws IOException If the <code>Widget</code> JavaScript is not found.
+   */
+  public final void renderDispose( final Widget widget ) throws IOException {
+    final JSWriter writer = JSWriter.getWriterFor( widget );
+    writer.dispose();
+  }
+  
+  private IUploadAdapter getAdapter( final Upload upload ) {
+    return ( IUploadAdapter )upload.getAdapter( IUploadAdapter.class );
+  }
+}
diff --git a/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/internal/uploadkit/UploadThemeAdapter.java b/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/internal/uploadkit/UploadThemeAdapter.java
new file mode 100644 (file)
index 0000000..cd3fe22
--- /dev/null
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2010 EclipseSource and others. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *   EclipseSource - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.rwt.widgets.internal.uploadkit;
+
+import org.eclipse.rwt.internal.theme.*;
+import org.eclipse.rwt.widgets.Upload;
+import org.eclipse.swt.internal.widgets.controlkit.ControlThemeAdapter;
+
+public class UploadThemeAdapter extends ControlThemeAdapter {
+
+  public int getButtonBorderWidth( final Upload upload ) {
+    SimpleSelector selector = new SimpleSelector( new String[] { "[PUSH" } );
+    QxType cssValue
+      = ThemeUtil.getCssValue( "Button", "border", selector, null );
+    return ( ( QxBorder )cssValue ).width;
+  }
+}
diff --git a/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/upload/servlet/FileUploadListener.java b/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/upload/servlet/FileUploadListener.java
new file mode 100644 (file)
index 0000000..310a5b3
--- /dev/null
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2002-2007 Critical Software S.A.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Tiago Rodrigues (Critical Software S.A.) - initial implementation
+ *     Joel Oliveira (Critical Software S.A.) - initial commit
+ ******************************************************************************/
+package org.eclipse.rwt.widgets.upload.servlet;
+
+import org.apache.commons.fileupload.ProgressListener;
+
+/**
+ * This is a File Upload Listener that is used by Apache Commons File Upload to
+ * monitor the progress of the uploaded file.
+ */
+public class FileUploadListener implements ProgressListener {
+
+  private volatile long bytesRead = 0L, contentLength = 0L, item = 0L;
+
+  /**
+   * Creates a new File Upload Listener.
+   */
+  public FileUploadListener() {
+    super();
+  }
+
+  /**
+   * Updates the File properties.
+   * 
+   * @param aBytesRead Number of bytes read.
+   * @param aContentLength The file length.
+   * @param anItem The monitored item.
+   */
+  public final void update( final long aBytesRead,
+                            final long aContentLength,
+                            final int anItem )
+  {
+    bytesRead = aBytesRead;
+    contentLength = aContentLength;
+    item = anItem;
+  }
+
+  /**
+   * Gets the number of bytes read.
+   * 
+   * @return Number of bytes read.
+   */
+  public final long getBytesRead() {
+    return bytesRead;
+  }
+
+  /**
+   * Gets the File length.
+   * 
+   * @return File length.
+   */
+  public final long getContentLength() {
+    return contentLength;
+  }
+
+  /**
+   * Gets the monitored item.
+   * 
+   * @return Monitored item.
+   */
+  public final long getItem() {
+    return item;
+  }
+}
diff --git a/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/upload/servlet/FileUploadServiceHandler.java b/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/upload/servlet/FileUploadServiceHandler.java
new file mode 100644 (file)
index 0000000..80216ae
--- /dev/null
@@ -0,0 +1,280 @@
+/*******************************************************************************
+ * Copyright (c) 2002-2006 Innoopract Informationssysteme GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     Innoopract Informationssysteme GmbH - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.rwt.widgets.upload.servlet;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.List;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.*;
+
+import org.apache.commons.fileupload.*;
+import org.apache.commons.fileupload.disk.DiskFileItemFactory;
+import org.apache.commons.fileupload.servlet.ServletFileUpload;
+import org.eclipse.rwt.RWT;
+import org.eclipse.rwt.internal.util.URLHelper;
+import org.eclipse.rwt.service.IServiceHandler;
+import org.eclipse.rwt.widgets.IUploadConfiguration;
+import org.eclipse.rwt.widgets.internal.UploadConfiguration;
+
+
+/**
+ * Handles file uploads and upload progress updates. 
+ * <p> 
+ * Implementation note: uploaded files are currently stored in the  
+ * java.io.tmpdir. See 
+ * {@link #handleFileUpload(HttpServletRequest, FileUploadStorageItem)} on
+ * how to change this.
+ * 
+ * @author stefan.roeck 
+ */
+public class FileUploadServiceHandler implements IServiceHandler {
+
+  private static final String REQUEST_WIDGET_ID = "widgetId";
+  private static final String REQUEST_PROCESS_ID = "processId";
+  private static final String XML_HEAD = "<?xml version=\"1.0\" encoding=\"utf-8\"?><response>";
+  
+  /**
+   * Holds configuration data for the upload widget.
+   */
+  private static final IUploadConfiguration uploadConfiguration = new UploadConfiguration();
+
+  /**
+   * Requests to this service handler without a valid session id are ignored for
+   * security reasons. The same applies to request with widgetIds which haven't been
+   * registered at the session singleton {@link FileUploadStorage}.
+   */
+  public void service() throws IOException, ServletException {
+    
+    final HttpServletRequest request = RWT.getRequest();
+    final String widgetId = request.getParameter( REQUEST_WIDGET_ID );
+    final String uploadProcessId = request.getParameter( REQUEST_PROCESS_ID );
+    final HttpSession session = request.getSession( false );
+    
+    if( session != null
+        && widgetId != null
+        && !"".equals( widgetId )
+        && uploadProcessId != null
+        && !"".equals( uploadProcessId ) )
+    {
+      final FileUploadStorage fileUploadStorage = FileUploadStorage.getInstance();
+      final FileUploadStorageItem fileUploadStorageItem = fileUploadStorage.getUploadStorageItem( widgetId );
+      
+      // fileUploadStorageItem can be null, if Upload widget is dispsed!
+      if (ServletFileUpload.isMultipartContent(request)) {
+        // Handle post-request which contains the file to upload
+        handleFileUpload( request, fileUploadStorageItem, uploadProcessId );
+      } else {
+        // This is probably a request for updating the progress bar
+        handleUpdateProgress( fileUploadStorageItem, uploadProcessId );
+      }
+      
+    }
+  }
+
+  /**
+   * Treats the request as a post request which contains the file to be
+   * uploaded. Uses the apache commons fileupload library to
+   * extract the file from the request, attaches a {@link FileUploadListener} to 
+   * get notified about the progress and writes the file content
+   * to the given {@link FileUploadStorageItem}
+   * @param request Request object, must not be null
+   * @param fileUploadStorageitem Object where the file content is set to.
+   * If null, nothing happens.
+   * @param uploadProcessId Each upload action has a unique process identifier to
+   * match subsequent polling calls to get the progress correctly to the uploaded file.
+   *
+   */
+  private void handleFileUpload( final HttpServletRequest request,
+                                 final FileUploadStorageItem fileUploadStorageitem, 
+                                 final String uploadProcessId )
+  {
+    // Ignore upload requests which have no valid widgetId
+    if (fileUploadStorageitem != null && uploadProcessId != null && !"".equals( uploadProcessId )) {
+      
+      // Reset storage item to clear values from last upload process
+      fileUploadStorageitem.reset();
+      
+      // Create file upload factory and upload servlet
+      // You could use new DiskFileItemFactory(threshold, location)
+      // to configure a custom in-memory threshold and storage location.
+      // By default the upload files are stored in the java.io.tmpdir
+      final FileItemFactory factory = new DiskFileItemFactory();
+      final ServletFileUpload upload = new ServletFileUpload( factory );
+      
+      // apply configuration params
+      applyConfiguration(upload);
+      
+      // Create a file upload progress listener
+      final ProgressListener listener = new ProgressListener() {
+
+        public void update( final long aBytesRead,
+                            final long aContentLength,
+                            final int anItem  ) {
+          fileUploadStorageitem.updateProgress( aBytesRead, aContentLength );
+        }
+        
+      };
+      // Upload servlet allows to set upload listener
+      upload.setProgressListener( listener );
+      fileUploadStorageitem.setUploadProcessId( uploadProcessId );
+      
+      FileItem fileItem = null;
+      try {
+        final List uploadedItems = upload.parseRequest( request );
+        // Only one file upload at once is supported. If there are multiple files, take
+        // the first one and ignore other
+        if ( uploadedItems.size() > 0 ) {
+          fileItem = ( FileItem )uploadedItems.get( 0 );
+          // Don't check for file size 0 because this prevents uploading new empty office xp documents
+          // which have a file size of 0.
+          if( !fileItem.isFormField() ) {
+            fileUploadStorageitem.setFileInputStream( fileItem.getInputStream() );
+            fileUploadStorageitem.setContentType(fileItem.getContentType());
+          }
+        }
+      } catch( final FileUploadException e ) {
+        fileUploadStorageitem.setException(e);
+      } catch( final Exception e ) {
+        fileUploadStorageitem.setException(e);
+      }
+    }
+  }
+
+  /**
+   * Applies custom configuration parameters specified by the
+   * user.
+   * @param upload The upload handler to which the config is applied.
+   */
+  private void applyConfiguration( final ServletFileUpload upload ) {
+    upload.setFileSizeMax( getConfiguration().getFileSizeMax() );
+    upload.setSizeMax( getConfiguration().getSizeMax() );
+  }
+
+  /**
+   * Treats the request as a get request which is triggered by the
+   * browser to retrieve the progress state. Gets the registered 
+   * {@link FileUploadListener} from the given {@link FileUploadStorageItem}
+   * to check the current progress. The result is written to the response
+   * in an XML format.
+   * <br>
+   * <b>Note:</b> It is important that a valid response is written in any case
+   * to let the Browser know, when polling can be stopped. 
+   * @param uploadProcessId 
+   */
+  private void handleUpdateProgress( final FileUploadStorageItem fileUploadStorageitem, final String uploadProcessId )
+    throws IOException
+  {
+    final HttpServletResponse response = RWT.getResponse();
+    final PrintWriter out = response.getWriter();
+    
+    final StringBuffer buffy = new StringBuffer( XML_HEAD );
+    long bytesRead = 0;
+    long contentLength = 0;
+    // Check to see if we've created the listener object yet
+    response.setContentType( "text/xml" );
+    response.setHeader( "Cache-Control", "no-cache" );
+    
+    if( fileUploadStorageitem != null ) {
+      
+      if ( uploadProcessId != null && uploadProcessId.equals( fileUploadStorageitem.getUploadProcessId() )) {
+        
+          // Get the meta information
+          bytesRead = fileUploadStorageitem.getBytesRead();
+          contentLength = fileUploadStorageitem.getContentLength();
+          /*
+           * XML Response Code
+           */
+          buffy.append( "<bytes_read>" );
+          buffy.append( bytesRead );
+          buffy.append( "</bytes_read><content_length>" );
+          buffy.append( contentLength );
+          buffy.append( "</content_length>" );
+          // Check to see if we're done
+          // Even files with a size of 0 have a content length > 0
+          if( contentLength != 0 ) {
+            if( bytesRead == contentLength ) {
+              buffy.append( "<finished />" );
+            } else {
+              // Calculate the percent complete
+              buffy.append( "<percent_complete>" );
+              buffy.append( ( 100 * bytesRead / contentLength ) );
+              buffy.append( "</percent_complete>" );
+            }
+          } else {
+            // Contentlength should not be 0, however, send finished to make sure
+            // the Browser side polling stops.
+            buffy.append( "<finished />" );
+          }
+      } else {
+        //System.out.println("No match: " + uploadProcessId + " " + fileUploadStorageitem.getUploadProcessId());
+        // if the processId doesn't match, return nothing
+        // which causes the client script to send another
+        // request after waiting. This could happen,
+        // if the first GET-request was send, before the
+        // Upload-POST request arrived.
+      }
+      
+    } else {
+      // if fileUploadStorageitem is null, the upload widget is disposed
+      // return "finished" to stop monitoring
+      buffy.append( "<finished />" );
+    }
+    
+    buffy.append( "</response>" );
+    out.println( buffy.toString() );
+    out.flush();
+    out.close();
+  }
+
+  /**
+   * Registers this service handler. This method should be called only once.
+   */
+  public static void register() {
+    final FileUploadServiceHandler instance = new FileUploadServiceHandler();
+    final String serviceHandlerId = getServiceHandlerId();
+    RWT.getServiceManager().registerServiceHandler(serviceHandlerId, instance);
+  }
+
+  /**
+   * Returns a unique id for this service handler class.
+   */
+  private static String getServiceHandlerId() {
+    final String serviceHandlerId = FileUploadServiceHandler.class.getName();
+    return serviceHandlerId;
+  }
+
+  /**
+   * Builds a url which points to the service handler and encodes the given parameters
+   * as url parameters. 
+   */
+  public static String getUrl(final String widgetId) {
+    final StringBuffer url = new StringBuffer();
+    url.append(URLHelper.getURLString(false));
+
+    URLHelper.appendFirstParam(url, REQUEST_PARAM, getServiceHandlerId());
+    URLHelper.appendParam(url, REQUEST_WIDGET_ID, widgetId);
+
+    // convert to relative URL
+    final int firstSlash = url.indexOf( "/" , url.indexOf( "//" ) + 2 ); // first slash after double slash of "http://"
+    url.delete( 0, firstSlash ); // Result is sth like "/rap?custom_service_handler..."
+    return RWT.getResponse().encodeURL(url.toString());
+  }
+  
+  /**
+   * Returns a configuration facade.
+   */
+  public static IUploadConfiguration getConfiguration() {
+    return uploadConfiguration;
+  }
+}
diff --git a/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/upload/servlet/FileUploadServlet.java b/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/upload/servlet/FileUploadServlet.java
new file mode 100644 (file)
index 0000000..30b9d69
--- /dev/null
@@ -0,0 +1,160 @@
+/*******************************************************************************
+ * Copyright (c) 2002-2007 Critical Software S.A. All rights reserved. This
+ * program and the accompanying materials are made available under the terms of
+ * the Eclipse Public License v1.0 which accompanies this distribution, and is
+ * available at http://www.eclipse.org/legal/epl-v10.html Contributors: Tiago
+ * Rodrigues (Critical Software S.A.) - initial implementation Joel Oliveira
+ * (Critical Software S.A.) - initial commit
+ ******************************************************************************/
+package org.eclipse.rwt.widgets.upload.servlet;
+
+import java.io.*;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.servlet.*;
+import javax.servlet.http.*;
+
+import org.apache.commons.fileupload.*;
+import org.apache.commons.fileupload.disk.DiskFileItemFactory;
+import org.apache.commons.fileupload.servlet.ServletFileUpload;
+
+/**
+ * This is a File Upload Servlet that is used with AJAX to monitor the progress
+ * of the uploaded file. It will return an XML object containing the meta
+ * information as well as the percent complete.
+ * @deprecated is replaced by {@link FileUploadServiceHandler} and will be deleted
+ * in a future version.
+ */
+public class FileUploadServlet extends HttpServlet implements Servlet {
+  private static final long serialVersionUID = 2740693677625051632L;
+  private static final String CONTEXT_TEMP_DIR
+    = "javax.servlet.context.tempdir";
+  private static final String XML_HEAD
+    = "<?xml version=\"1.0\" encoding=\"utf-8\"?><response>";
+
+  /**
+   * Creates a new instance of the File Upload Servlet.
+   */
+  public FileUploadServlet() {
+    super();
+  }
+
+  /**
+   * Handles the GET to return the upload status.
+   * 
+   * @param request HTTP request.
+   * @param response HTTP response.
+   */
+  protected void doGet( final HttpServletRequest request,
+                        final HttpServletResponse response )
+    throws ServletException, IOException
+  {
+    final PrintWriter out = response.getWriter();
+    HttpSession session = request.getSession();
+    FileUploadListener listener = null;
+    final StringBuffer buffy = new StringBuffer( XML_HEAD );
+    long bytesRead = 0;
+    long contentLength = 0;
+    if( session != null ) {
+      // Check to see if we've created the listener object yet
+      listener = ( FileUploadListener )session.getAttribute( "LISTENER" );
+      response.setContentType( "text/xml" );
+      response.setHeader( "Cache-Control", "no-cache" );
+      if( listener != null ) {
+        // Get the meta information
+        bytesRead = listener.getBytesRead();
+        contentLength = listener.getContentLength();
+        /*
+         * XML Response Code
+         */
+        buffy.append( "<bytes_read>" );
+        buffy.append( bytesRead );
+        buffy.append( "</bytes_read><content_length>" );
+        buffy.append( contentLength );
+        buffy.append( "</content_length>" );
+        // Check to see if we're done
+        if( contentLength != 0 ) {
+          if( bytesRead == contentLength ) {
+            buffy.append( "<finished />" );
+            // No reason to keep listener in session since we're done
+            session.setAttribute( "LISTENER", null );
+          } else {
+            // Calculate the percent complete
+            buffy.append( "<percent_complete>" );
+            buffy.append( ( 100 * bytesRead / contentLength ) );
+            buffy.append( "</percent_complete>" );
+          }
+        }
+      }
+      buffy.append( "</response>" );
+      out.println( buffy.toString() );
+      out.flush();
+      out.close();
+    }
+  }
+
+  /**
+   * Handles the POST to receive the file and saves it to the user TMP
+   * directory.
+   * 
+   * @param request HTTP request.
+   * @param response HTTP response.
+   */
+  protected void doPost( final HttpServletRequest request,
+                         final HttpServletResponse response )
+    throws ServletException, IOException
+  {
+    // Create file upload factory and upload servlet
+    FileItemFactory factory = new DiskFileItemFactory();
+    ServletFileUpload upload = new ServletFileUpload( factory );
+    // Set file upload progress listener
+    final FileUploadListener listener = new FileUploadListener();
+    HttpSession session = request.getSession();
+    session.setAttribute( "LISTENER", listener );
+    // Upload servlet allows to set upload listener
+    upload.setProgressListener( listener );
+    FileItem fileItem = null;
+    final File filePath = getUploadTempDir( session );
+    try {
+      // Iterate over all uploaded files
+      final List uploadedItems = upload.parseRequest( request );
+      final Iterator iterator = uploadedItems.iterator();
+      while( iterator.hasNext() ) {
+        fileItem = ( FileItem )iterator.next();
+        if( !fileItem.isFormField() && fileItem.getSize() > 0 ) {
+          final String myFullFileName = fileItem.getName();
+          final String slashType =   myFullFileName.lastIndexOf( "\\" ) > 0
+                                   ? "\\"
+                                   : "/";
+          final int startIndex = myFullFileName.lastIndexOf( slashType );
+          // Ignore the path and get the filename
+          String myFileName 
+            = myFullFileName.substring( startIndex + 1,
+                                        myFullFileName.length() );
+          // Write the uploaded file to the system
+          File file = new File( filePath, myFileName );
+          fileItem.write( file );
+        }
+      }
+    } catch( FileUploadException e ) {
+      e.printStackTrace();
+    } catch( final Exception e ) {
+      e.printStackTrace();
+    }
+  }
+
+  public static File getUploadTempDir( final HttpSession session ) {
+    ServletContext context = session.getServletContext();
+    StringBuffer path = new StringBuffer();
+    File tempDir = ( File )context.getAttribute( CONTEXT_TEMP_DIR );
+    path.append( tempDir.getAbsolutePath() );
+    path.append( File.separatorChar );
+    path.append( session.getId() );
+    File result = new File ( path.toString() );
+    if( !result.exists() ) {
+      result.mkdir();
+    }
+    return result;
+  }
+}
diff --git a/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/upload/servlet/FileUploadStorage.java b/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/upload/servlet/FileUploadStorage.java
new file mode 100644 (file)
index 0000000..5fc6479
--- /dev/null
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2002-2006 Innoopract Informationssysteme GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     Innoopract Informationssysteme GmbH - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.rwt.widgets.upload.servlet;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.rwt.SessionSingletonBase;
+
+
+/**
+ * This session singleton is used to communicate between service handler and rap
+ * application and to exchange a reference to the uploaded file. To support multiple
+ * file uploads a key must be used to get and store items. This key must be unique as
+ * it is used as a hash map key.
+ * @author stefan.roeck
+ */
+public class FileUploadStorage extends SessionSingletonBase {
+
+  private Map items = new HashMap();
+  
+  /**
+   * Returns an instance to this session singleton.
+   */
+  public static FileUploadStorage getInstance() {
+    return ( FileUploadStorage )getInstance( FileUploadStorage.class );
+  }
+  
+  private FileUploadStorage() {
+    // prevent instantiation
+  }
+  
+  /**
+   * Sets a {@link FileUploadStorageItem} or removes an existing one, if the item is null.
+   */
+  public void setUploadStorageItem(final String key, final FileUploadStorageItem item) {
+    if( item == null ) {
+      items.remove( key );
+    } else {
+      items.put( key, item );
+    }
+  }
+  
+  /**
+   * Returns a {@link FileUploadStorageItem} for the given key or null, if not existant
+   * in map.
+   */
+  public FileUploadStorageItem getUploadStorageItem(final String key) {
+    return ( FileUploadStorageItem )items.get( key );
+  }
+  
+}
diff --git a/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/upload/servlet/FileUploadStorageItem.java b/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/upload/servlet/FileUploadStorageItem.java
new file mode 100644 (file)
index 0000000..4434b42
--- /dev/null
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Copyright (c) 2002-2006 Innoopract Informationssysteme GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     Innoopract Informationssysteme GmbH - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.rwt.widgets.upload.servlet;
+
+import java.io.InputStream;
+
+
+/**
+ * This Pojo is used to store a file reference and a progress listener.
+ * It is used for communication between service handler and rap application.
+ * Due to the asynchronous nature of ServiceHandler-requests and access from
+ * the UIThread to instances of this class, all members are access
+ * synchronized.
+ * 
+ * @author stefan.roeck
+ */
+public class FileUploadStorageItem {
+  private InputStream fileInputStream;
+  private String contentType;
+  private String uploadProcessId;
+  private long bytesRead;
+  private long contentLength;
+  private Exception exception;
+  
+  
+  public FileUploadStorageItem() {
+    reset();
+  }
+  
+  public synchronized InputStream getFileInputStream() {
+    return this.fileInputStream;
+  }
+  
+  public synchronized void setFileInputStream( final InputStream fileInputStream ) {
+    this.fileInputStream = fileInputStream;
+  }
+  
+  public synchronized void setContentType( final String contentType ) {
+    this.contentType = contentType;
+  }
+  
+  public synchronized String getContentType() {
+    return this.contentType;
+  }
+
+  public synchronized void setUploadProcessId( final String uploadProcessId ) {
+    this.uploadProcessId = uploadProcessId;
+  }
+  
+  public synchronized String getUploadProcessId() {
+    return this.uploadProcessId;
+  }
+  
+  public synchronized void updateProgress(final long bytesRead, final long contentLength) {
+    this.bytesRead = bytesRead;
+    this.contentLength = contentLength;
+  }
+
+  public synchronized long getBytesRead() {
+    return bytesRead;
+  }
+  
+  public synchronized long getContentLength() {
+    return contentLength;
+  }
+
+  public synchronized void reset() {
+    contentLength = -1;
+    bytesRead = -1;
+    contentType = null;
+    fileInputStream = null;
+    exception = null;
+  }
+
+  public synchronized void setException( Exception e ) {
+    this.exception = e;
+  }
+  
+  public synchronized Exception getException() {
+    return exception;
+  }
+}