Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Ticket #2553 (closed defect: duplicate)

Opened 4 years ago

Last modified 3 years ago

ActionWebService SOAP Call Fails w/ Parameters - TypeError (can't modify frozen object):

Reported by: Joe Assigned to: anonymous
Priority: high Milestone:
Component: ActionWebService Version: 1.0.0
Severity: blocker Keywords: SOAP AWS
Cc: phil.swenson@gmail.com, ludvig.omholt@it.su.se

Description

When moving to ruby version 1.8.3 this error happens when invoking a SOAP web service using parameters.

Stack Trace: TypeError (can't modify frozen object):

/usr/local/lib/ruby/1.8/xsd/qname.rb:78:in `name=' /usr/local/lib/ruby/1.8/soap/rpc/element.rb:118:in `set_param' /usr/local/lib/ruby/1.8/soap/rpc/element.rb:116:in `set_param' /vendor/rails/actionwebservice/lib/action_web_service/protocol/soap_protocol.rb:78:in `encode_request' /vendor/rails/actionwebservice/lib/action_web_service/scaffolding.rb:79:in `invoke_submit' /usr/local/lib/ruby/1.8/benchmark.rb:293:in `measure' /vendor/rails/actionwebservice/lib/action_web_service/scaffolding.rb:68:in `invoke_submit' /vendor/rails/actionpack/lib/action_controller/base.rb:832:in `perform_action_without_filters' /vendor/rails/actionpack/lib/action_controller/filters.rb:295:in `perform_action_without_benchmark' /vendor/rails/actionpack/lib/action_controller/benchmarking.rb:69:in `perform_action_without_rescue' /usr/local/lib/ruby/1.8/benchmark.rb:293:in `measure' /vendor/rails/actionpack/lib/action_controller/benchmarking.rb:69:in `perform_action_without_rescue' /vendor/rails/actionpack/lib/action_controller/rescue.rb:82:in `perform_action' /vendor/rails/actionpack/lib/action_controller/base.rb:365:in `process_without_session_management_support' /vendor/rails/actionpack/lib/action_controller/session_management.rb:116:in `process' /vendor/rails/railties/lib/dispatcher.rb:36:in `dispatch' /vendor/rails/railties/lib/webrick_server.rb:117:in `handle_dispatch' /vendor/rails/railties/lib/webrick_server.rb:83:in `service' /usr/local/lib/ruby/1.8/webrick/httpserver.rb:104:in `service' /usr/local/lib/ruby/1.8/webrick/httpserver.rb:65:in `run' /usr/local/lib/ruby/1.8/webrick/server.rb:173:in `start_thread' /usr/local/lib/ruby/1.8/webrick/server.rb:162:in `start_thread' /usr/local/lib/ruby/1.8/webrick/server.rb:95:in `start' /usr/local/lib/ruby/1.8/webrick/server.rb:92:in `start' /usr/local/lib/ruby/1.8/webrick/server.rb:23:in `start' /usr/local/lib/ruby/1.8/webrick/server.rb:82:in `start' /vendor/rails/railties/lib/webrick_server.rb:69:in `dispatch' script/server:49

I've tried this with both the latest rails and edge rails.

If I move back to ruby 1.8.2 this error no longer appears - however I need some other features from ruby 1.8.3 so I'm a little stuck here.

Is there a workaround for this yet?

Thanks.

Attachments

fix_aws_soap.tar.gz (0.8 kB) - added by johnwilger@gmail.com on 01/04/06 15:46:24.
Leon's AWS patch repackaged as a plugin (for people who don't want to patch Rails directly)

Change History

10/26/05 17:07:52 changed by Brian Bugh

This is a big hack, mostly because I have absolutely no idea what else this affects. I stumbled through fixing this with a lot of breakpoints and guessing. It made my problems go away, though. Both changes must be made together or you just get different error messages.

/usr/local/lib/ruby/1.8/xsd/qname.rb

74c74
<   EMPTY = QName.new.freeze
---
>   EMPTY = QName.new

and

Index: actionwebservice/lib/action_web_service/casting.rb
===================================================================
--- actionwebservice/lib/action_web_service/casting.rb  (revision 2752)
+++ actionwebservice/lib/action_web_service/casting.rb  (working copy)
@@ -92,6 +92,7 @@
         end

         def cast_to_structured_type(value, signature_type) # :nodoc:
+               return value
           obj = nil
           obj = value if canonical_type(value.class) == canonical_type(signature_type.type)
           obj ||= signature_type.type_class.new

Sorry I could't be more useful by fixing it.

11/04/05 16:17:39 changed by phil.swenson@gmail.com

I'm having the same problem with 1.8.2

11/05/05 01:19:42 changed by anonymous

any info on when this will be fixed or a work around? does a beta version of rails fix this?

11/05/05 21:05:08 changed by david

  • owner changed from David to bitserf@gmail.com.

11/08/05 12:17:39 changed by anonymous

  • priority changed from high to highest.

I have this problem on 183. haven't been able to try on 183 as I'm on windows and I haven't been able to get 183 working on Windows.

I tried the hack mentioned above and was able to successfully produce web services, but when I tried calling the web service from code I got another exception (sorry, don't have the exception handy).

I think this is a critical error given that a major piece of the action framework is completely unusable.

11/08/05 18:12:43 changed by bitserf@gmail.com

  • cc set to phil.swenson@gmail.com.
  • owner changed from bitserf@gmail.com to anonymous.
  • status changed from new to assigned.

Hi guys,

Sorry about the delay, could you provide me with the exact builds of Ruby you are using? As this appears to be an issue inside SOAP4R (or at least our usage of it), I'd like to know what I'm working with.

1.8.2 is unfortunately not "precise" enough as a version specifier.

Thanks Leon

11/08/05 22:22:38 changed by phil.swenson@gmail.com

let me know if you need more info..

Running on windows....

ruby --version: ruby 1.8.2 (2004-12-25) [i386-mswin32]

gem list: *** LOCAL GEMS ***

actionmailer (1.0.1)

Service layer for easy email delivery and testing.

actionpack (1.9.1)

Web-flow and rendering framework putting the VC in MVC.

actionwebservice (0.8.1)

Web service support for Action Pack.

activerecord (1.11.1)

Implements the ActiveRecord pattern for ORM.

activesupport (1.1.1)

Support and utility classes used by the Rails framework.

cmdparse (2.0.0)

Advanced command line parser supporting commands

fxri (0.3.2)

Graphical interface to the RI documentation, with search engine.

fxruby (1.2.6)

FXRuby is the Ruby binding to the FOX GUI toolkit.

highline (1.0.1)

HighLine is a high-level line oriented console interface.

log4r (1.0.5)

Log4r is a comprehensive and flexible logging library for Ruby.

rails (0.13.1)

Web-application framework with template engine, control-flow layer, and ORM.

rake (0.6.2)

Ruby based make-like utility.

rubyful_soup (1.0.1)

An HTML/XML parser that handles bad markup and provides tree traversal methods.

rubyzip (0.5.12)

rubyzip is a ruby module for reading and writing zip files

sources (0.0.1)

This package provides download sources for remote gem installation

- Show quoted text -

11/09/05 03:21:38 changed by bitserf@gmail.com

As you're experiencing it on 1.8.2 final on Windows, but that same version works for other platforms, could you let me know which build of Ruby (with URL) you installed on Windows?

I'd like to reproduce it on a Windows installation here.

Thanks

11/09/05 05:25:42 changed by ludvig.omholt@it.su.se

I have this problem using soap 1.5.5 in both ruby 1.8.2 and 1.8.3.

irb(main):001:0> require 'soap/soap'
=> true
irb(main):002:0> SOAP::VERSION
=> "1.5.5"

11/14/05 09:44:24 changed by bitserf@gmail.com

  • cc changed from phil.swenson@gmail.com to phil.swenson@gmail.com, ludvig.omholt@it.su.se.

Hi guys,

Think I've found the problem, I've reproduced it with SOAP4R 1.5.5 on Ruby 1.8.2.

Could you try this patch (a quick workaround) against lib/action_web_service/protocol/soap_protocol.rb?

Index: lib/action_web_service/protocol/soap_protocol.rb
===================================================================
--- lib/action_web_service/protocol/soap_protocol.rb	(revision 3022)
+++ lib/action_web_service/protocol/soap_protocol.rb	(working copy)
@@ -62,19 +62,32 @@
           Request.new(self, method_name, params, service_name, nil, nil, protocol_options)
         end
 
-        def encode_request(method_name, params, param_types)
+        def encode_request(method_name, params, param_types)
+          # workaround for newer versions of SOAP4R: SOAPMethodRequest#set_params() now expects an object.
+          pack_params = SOAP::Version >= "1.5.5" ? true : false
+	  
           param_types.each{ |type| marshaler.register_type(type) } if param_types
           qname = XSD::QName.new(marshaler.namespace, method_name)
           param_def = []
           if param_types
             params = param_types.zip(params).map do |type, param|
-              param_def << ['in', type.name, marshaler.lookup_type(type).mapping]
-              [type.name, marshaler.ruby_to_soap(param)]
+              param_def << ['in', type.name.to_s, marshaler.lookup_type(type).mapping]
+              [type.name.to_s, pack_params ? param : marshaler.ruby_to_soap(param)]
             end
           else
             params = []
           end
-          request = SOAP::RPC::SOAPMethodRequest.new(qname, param_def)
+          request = SOAP::RPC::SOAPMethodRequest.new(qname, param_def)
+          if pack_params
+            names = request.input_params
+            o = Object.new
+            idx = 0
+            while idx < params.length
+              o.instance_variable_set('@' + names[idx], params[idx][1])
+              idx += 1
+            end
+            params = marshaler.ruby_to_soap(o)            
+          end
           request.set_param(params)
           envelope = create_soap_envelope(request)
           SOAP::Processor.marshal(envelope)

Let me know if this fixes it for you, and I'll try come up with a better solution.

Thanks

Leon

11/14/05 09:51:52 changed by ludvig.omholt@it.su.se

The patch works fine for me in both 1.8.2 and 1.8.3 with soap4r 1.5.5.

11/14/05 14:26:15 changed by pelle@neubia.com

This works for me as well on 1.8.3 under openbsd.

11/26/05 17:43:39 changed by Mohit Muthanna (mohit AT muthanna AT removethis DOT com)

  • version changed from 0.9.1 to 0.9.3.

I had this same issue on Linux. Drove me nuts. The patch works great.

My environment:

ruby 1.8.3 (2005-09-21) [i686-linux] actionwebservice 0.9.3, 0.9.2 - (Both versions are defective)

irb(main):001:0> require 'soap/soap' => true irb(main):002:0> SOAP::VERSION => "1.5.5"

Thanks, Mohit.

01/04/06 15:24:49 changed by johnwilger@gmail.com

I'm also experiencing this issue with Ruby 1.8.4 and AWS 1.0.0. The patch provided by Leon seems to solve the problem.

ruby 1.8.4 (2005-12-24) [i686-linux]

01/04/06 15:27:53 changed by anonymous

  • version changed from 0.9.3 to 1.0.0.

01/04/06 15:46:24 changed by johnwilger@gmail.com

  • attachment fix_aws_soap.tar.gz added.

Leon's AWS patch repackaged as a plugin (for people who don't want to patch Rails directly)

02/06/06 23:20:52 changed by anonymous

There seems to be a issue with the uploaded file.

Any news when this patch is going to be applied

02/26/06 21:08:12 changed by Kent Sibilev

This is the smallest fix for this problem:

Index: actionwebservice/lib/action_web_service/protocol/soap_protocol/marshaler.rb =================================================================== --- actionwebservice/lib/action_web_service/protocol/soap_protocol/marshaler.rb (revision 3668) +++ actionwebservice/lib/action_web_service/protocol/soap_protocol/marshaler.rb (working copy) @@ -32,7 +32,9 @@

end

def ruby_to_soap(obj)

- SOAP::Mapping.obj2soap(obj, @registry) + soap = SOAP::Mapping.obj2soap(obj, @registry) + soap.elename = XSD::QName.new if SOAP::Version >= "1.5.5" && soap.elename == XSD::QName::EMPTY + soap

end

def register_type(type)

02/26/06 21:09:05 changed by Kent Sibilev

Oops, wrong formatting. Another try:

Index: actionwebservice/lib/action_web_service/protocol/soap_protocol/marshaler.rb
===================================================================
--- actionwebservice/lib/action_web_service/protocol/soap_protocol/marshaler.rb (revision 3668)
+++ actionwebservice/lib/action_web_service/protocol/soap_protocol/marshaler.rb (working copy)
@@ -32,7 +32,9 @@
         end
 
         def ruby_to_soap(obj)
-          SOAP::Mapping.obj2soap(obj, @registry)
+          soap = SOAP::Mapping.obj2soap(obj, @registry)
+          soap.elename = XSD::QName.new if SOAP::Version >= "1.5.5" && soap.elename == XSD::QName::EMPTY
+          soap
         end
 
         def register_type(type)

03/01/06 19:34:51 changed by Kent Sibilev

  • status changed from assigned to closed.
  • resolution set to duplicate.

see ticket #4038

07/22/06 07:47:55 changed by anonymous

beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita beita

08/17/06 09:05:43 changed by anonymous

xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao xiao