1 |
|
/* |
2 |
|
* DotGNU XmlRpc implementation |
3 |
|
* |
4 |
|
* Copyright (C) 2003 Free Software Foundation, Inc. |
5 |
|
* |
6 |
|
* This program is free software; you can redistribute it and/or modify |
7 |
|
* it under the terms of the GNU General Public License as published by |
8 |
|
* the Free Software Foundation; either version 2 of the License, or |
9 |
|
* (at your option) any later version. |
10 |
|
* |
11 |
|
* This program is distributed in the hope that it will be useful, |
12 |
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 |
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 |
|
* GNU General Public License for more details. |
15 |
|
* |
16 |
|
* You should have received a copy of the GNU General Public License |
17 |
|
* along with this program; if not, write to the Free Software |
18 |
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA |
19 |
|
* |
20 |
|
* $Revision$ $Date$ |
21 |
|
* |
22 |
|
* -------------------------------------------------------------------------- |
23 |
|
*/ |
24 |
|
//using System.Reflection; |
25 |
|
using System.Collections; |
26 |
|
using System.Globalization; |
27 |
|
using System.IO; |
28 |
|
using System.Xml; |
29 |
|
|
30 |
|
namespace DotGNU.XmlRpc |
31 |
|
{ |
32 |
|
public abstract class XmlRpcObject : ArrayList |
33 |
|
{ |
34 |
|
private DateTimeFormatInfo dateFormat; |
35 |
|
private Stack containerStack; |
36 |
|
private object value; |
37 |
|
private string text; |
38 |
|
protected string methodName; |
39 |
|
private string nodeName; |
40 |
|
private XmlTextReader reader; |
41 |
|
|
42 |
|
public XmlRpcObject() |
43 |
|
{ |
44 |
|
this.dateFormat = new DateTimeFormatInfo(); |
45 |
|
} |
46 |
|
|
47 |
|
public void Read( XmlTextReader reader ) |
48 |
|
{ |
49 |
|
this.reader = reader; |
50 |
|
Read(); |
51 |
|
} |
52 |
|
|
53 |
|
private void Read() { |
54 |
|
containerStack = new Stack(); |
55 |
|
|
56 |
|
// Itereate through the tree and construct an n-ary tree with |
57 |
|
// XmlRpcNodes so we can detect protocol errors and the current |
58 |
|
// scope/context of a value parameter. |
59 |
|
while( reader.Read() ) { |
60 |
|
switch( reader.NodeType ) { |
61 |
|
// |
62 |
|
// ELEMENT OPEN |
63 |
|
// |
64 |
|
case XmlNodeType.Element: |
65 |
|
nodeName = reader.Name; |
66 |
|
switch( nodeName ) { |
67 |
|
case "value": |
68 |
|
value = null; |
69 |
|
text = null; |
70 |
|
break; |
71 |
|
case "struct": |
72 |
|
PushScope( new XmlRpcStruct() ); |
73 |
|
break; |
74 |
|
case "array": |
75 |
|
PushScope( new XmlRpcArray() ); |
76 |
|
break; |
77 |
|
} |
78 |
|
break; |
79 |
|
|
80 |
|
// |
81 |
|
// ELEMENT TEXT |
82 |
|
// |
83 |
|
case XmlNodeType.Text: |
84 |
|
text = reader.Value; |
85 |
|
switch( nodeName ) { |
86 |
|
case "methodName": |
87 |
|
methodName = text; |
88 |
|
break; |
89 |
|
default: |
90 |
|
AddValue(); |
91 |
|
break; |
92 |
|
} |
93 |
|
break; |
94 |
|
|
95 |
|
// |
96 |
|
// ELEMENT CLOSE |
97 |
|
// |
98 |
|
case XmlNodeType.EndElement: |
99 |
|
switch( reader.Name ) { |
100 |
|
case "struct": |
101 |
|
case "array": |
102 |
|
object closedScope = containerStack.Pop(); |
103 |
|
|
104 |
|
// now determine whether the bugger aint nested... |
105 |
|
if( containerStack.Count > 0 ) { |
106 |
|
// aaah yes. nested. add him to the current stack object |
107 |
|
object stackObject = containerStack.Peek(); |
108 |
|
if( stackObject is XmlRpcStruct ) { |
109 |
|
((XmlRpcStruct)stackObject).value = closedScope; |
110 |
|
} |
111 |
|
else if( stackObject is XmlRpcArray ) { |
112 |
|
((XmlRpcArray)stackObject).Add( closedScope ); |
113 |
|
} |
114 |
|
} |
115 |
|
else { |
116 |
|
Add( closedScope ); |
117 |
|
} |
118 |
|
break; |
119 |
|
case "member": |
120 |
|
object stackObject; |
121 |
|
if( containerStack.Count > 0 ) { |
122 |
|
stackObject = containerStack.Peek(); |
123 |
|
if( stackObject is XmlRpcStruct ) { |
124 |
|
((XmlRpcStruct)stackObject).Commit(); |
125 |
|
} |
126 |
|
} |
127 |
|
break; |
128 |
|
} //switch |
129 |
|
break; // switch XmlNodeType.EndElement |
130 |
|
} |
131 |
|
} // reader.Read() |
132 |
|
} |
133 |
|
|
134 |
|
private void AddValue() |
135 |
|
{ |
136 |
|
object o; |
137 |
|
switch( nodeName ) { |
138 |
|
case "i4": |
139 |
|
case "int": |
140 |
|
o = Int32.Parse( text ); |
141 |
|
break; |
142 |
|
case "boolean": |
143 |
|
if( text == "0" ) { |
144 |
|
text = "false"; |
145 |
|
} |
146 |
|
else { |
147 |
|
text = "true"; |
148 |
|
} |
149 |
|
o = Convert.ToBoolean( text ); |
150 |
|
break; |
151 |
|
case "double": |
152 |
|
o = Double.Parse( text ); |
153 |
|
break; |
154 |
|
case "dateTime.iso8601": |
155 |
|
try { |
156 |
|
o = DateTime.ParseExact( text, "s", dateFormat ); |
157 |
|
} |
158 |
|
catch( FormatException e ){ |
159 |
|
string str = |
160 |
|
String.Format |
161 |
|
( "Cannot parse DateTime value: {0}, expected format is: {1}", |
162 |
|
text, dateFormat.SortableDateTimePattern ); |
163 |
|
throw new XmlRpcBadFormatException( 200, str ); |
164 |
|
} |
165 |
|
break; |
166 |
|
case "base64": |
167 |
|
o = Convert.FromBase64String( text ); |
168 |
|
break; |
169 |
|
case "string": |
170 |
|
case "name": |
171 |
|
o = text; |
172 |
|
break; |
173 |
|
} |
174 |
|
|
175 |
|
object stackObject; |
176 |
|
if( containerStack.Count > 0 ) { |
177 |
|
stackObject = containerStack.Peek(); |
178 |
|
if( stackObject is XmlRpcStruct ) { |
179 |
|
switch( nodeName ) { |
180 |
|
case "name": |
181 |
|
((XmlRpcStruct)stackObject).key = text; |
182 |
|
break; |
183 |
|
default: |
184 |
|
((XmlRpcStruct)stackObject).value = o; |
185 |
|
break; |
186 |
|
} |
187 |
|
} |
188 |
|
else if( stackObject is XmlRpcArray ) { |
189 |
|
((XmlRpcArray)stackObject).Add( o ); |
190 |
|
} |
191 |
|
} |
192 |
|
else { |
193 |
|
Add( o ); |
194 |
|
} |
195 |
|
} |
196 |
|
|
197 |
|
private void PushScope( Object o ) |
198 |
|
{ |
199 |
|
containerStack.Push( o ); |
200 |
|
} |
201 |
|
} |
202 |
|
} |
203 |
|
|