aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorJeff Ames2007-10-29 07:57:38 +0000
committerJeff Ames2007-10-29 07:57:38 +0000
commit7c6ef95f2f8a4fb06a1359e9625e80e4cb216a5d (patch)
treeae94989730f354f17619da74ca23eb2f1994f6b1
parentshould help with ODE bounce on region cross (diff)
downloadopensim-SC_OLD-7c6ef95f2f8a4fb06a1359e9625e80e4cb216a5d.zip
opensim-SC_OLD-7c6ef95f2f8a4fb06a1359e9625e80e4cb216a5d.tar.gz
opensim-SC_OLD-7c6ef95f2f8a4fb06a1359e9625e80e4cb216a5d.tar.bz2
opensim-SC_OLD-7c6ef95f2f8a4fb06a1359e9625e80e4cb216a5d.tar.xz
normalized line endings
-rw-r--r--OpenSim/Framework/Communications/Cache/GridAssetClient.cs320
-rw-r--r--OpenSim/Grid/AssetServer/RestService.cs218
-rw-r--r--OpenSim/Region/Environment/Interfaces/IAvatarFactory.cs26
-rw-r--r--OpenSim/Region/Environment/Modules/AvatarFactoryModule.cs114
4 files changed, 339 insertions, 339 deletions
diff --git a/OpenSim/Framework/Communications/Cache/GridAssetClient.cs b/OpenSim/Framework/Communications/Cache/GridAssetClient.cs
index fc77431..7483582 100644
--- a/OpenSim/Framework/Communications/Cache/GridAssetClient.cs
+++ b/OpenSim/Framework/Communications/Cache/GridAssetClient.cs
@@ -1,160 +1,160 @@
1/* 1/*
2* Copyright (c) Contributors, http://www.openmetaverse.org/ 2* Copyright (c) Contributors, http://www.openmetaverse.org/
3* See CONTRIBUTORS.TXT for a full list of copyright holders. 3* See CONTRIBUTORS.TXT for a full list of copyright holders.
4* 4*
5* Redistribution and use in source and binary forms, with or without 5* Redistribution and use in source and binary forms, with or without
6* modification, are permitted provided that the following conditions are met: 6* modification, are permitted provided that the following conditions are met:
7* * Redistributions of source code must retain the above copyright 7* * Redistributions of source code must retain the above copyright
8* notice, this list of conditions and the following disclaimer. 8* notice, this list of conditions and the following disclaimer.
9* * Redistributions in binary form must reproduce the above copyright 9* * Redistributions in binary form must reproduce the above copyright
10* notice, this list of conditions and the following disclaimer in the 10* notice, this list of conditions and the following disclaimer in the
11* documentation and/or other materials provided with the distribution. 11* documentation and/or other materials provided with the distribution.
12* * Neither the name of the OpenSim Project nor the 12* * Neither the name of the OpenSim Project nor the
13* names of its contributors may be used to endorse or promote products 13* names of its contributors may be used to endorse or promote products
14* derived from this software without specific prior written permission. 14* derived from this software without specific prior written permission.
15* 15*
16* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY 16* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY
17* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY 19* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26* 26*
27*/ 27*/
28using System; 28using System;
29using System.IO; 29using System.IO;
30using System.Threading; 30using System.Threading;
31using System.Reflection; 31using System.Reflection;
32using System.Xml.Serialization; 32using System.Xml.Serialization;
33 33
34using libsecondlife; 34using libsecondlife;
35 35
36using Nini.Config; 36using Nini.Config;
37using OpenSim.Framework.Console; 37using OpenSim.Framework.Console;
38using OpenSim.Framework.Interfaces; 38using OpenSim.Framework.Interfaces;
39using OpenSim.Framework.Types; 39using OpenSim.Framework.Types;
40using OpenSim.Framework.Utilities; 40using OpenSim.Framework.Utilities;
41using OpenSim.Framework.Communications; 41using OpenSim.Framework.Communications;
42 42
43namespace OpenSim.Framework.Communications.Cache 43namespace OpenSim.Framework.Communications.Cache
44{ 44{
45 public class GridAssetClient : IAssetServer 45 public class GridAssetClient : IAssetServer
46 { 46 {
47 private string _assetServerUrl; 47 private string _assetServerUrl;
48 private IAssetReceiver _receiver; 48 private IAssetReceiver _receiver;
49 49
50 public GridAssetClient(string serverUrl) 50 public GridAssetClient(string serverUrl)
51 { 51 {
52 _assetServerUrl = serverUrl; 52 _assetServerUrl = serverUrl;
53 } 53 }
54 54
55 #region IAssetServer Members 55 #region IAssetServer Members
56 56
57 public void SetReceiver(IAssetReceiver receiver) 57 public void SetReceiver(IAssetReceiver receiver)
58 { 58 {
59 _receiver = receiver; 59 _receiver = receiver;
60 } 60 }
61 61
62 public void FetchAsset(LLUUID assetID, bool isTexture) 62 public void FetchAsset(LLUUID assetID, bool isTexture)
63 { 63 {
64 Stream s = null; 64 Stream s = null;
65 try 65 try
66 { 66 {
67 67
68 MainLog.Instance.Debug("ASSETCACHE", "Querying for {0}", assetID.ToString()); 68 MainLog.Instance.Debug("ASSETCACHE", "Querying for {0}", assetID.ToString());
69 69
70 RestClient rc = new RestClient(_assetServerUrl); 70 RestClient rc = new RestClient(_assetServerUrl);
71 rc.AddResourcePath("assets"); 71 rc.AddResourcePath("assets");
72 rc.AddResourcePath(assetID.ToString()); 72 rc.AddResourcePath(assetID.ToString());
73 if (isTexture) 73 if (isTexture)
74 rc.AddQueryParameter("texture"); 74 rc.AddQueryParameter("texture");
75 75
76 rc.RequestMethod = "GET"; 76 rc.RequestMethod = "GET";
77 s = rc.Request(); 77 s = rc.Request();
78 78
79 if (s.Length > 0) 79 if (s.Length > 0)
80 { 80 {
81 XmlSerializer xs = new XmlSerializer(typeof(AssetBase)); 81 XmlSerializer xs = new XmlSerializer(typeof(AssetBase));
82 AssetBase asset = (AssetBase)xs.Deserialize(s); 82 AssetBase asset = (AssetBase)xs.Deserialize(s);
83 83
84 _receiver.AssetReceived(asset, isTexture); 84 _receiver.AssetReceived(asset, isTexture);
85 } 85 }
86 else 86 else
87 { 87 {
88 MainLog.Instance.Debug("ASSETCACHE", "Asset not found {0}", assetID.ToString()); 88 MainLog.Instance.Debug("ASSETCACHE", "Asset not found {0}", assetID.ToString());
89 _receiver.AssetNotFound(assetID); 89 _receiver.AssetNotFound(assetID);
90 } 90 }
91 } 91 }
92 catch (Exception e) 92 catch (Exception e)
93 { 93 {
94 MainLog.Instance.Error("ASSETCACHE", e.Message); 94 MainLog.Instance.Error("ASSETCACHE", e.Message);
95 MainLog.Instance.Error("ASSETCACHE", e.StackTrace); 95 MainLog.Instance.Error("ASSETCACHE", e.StackTrace);
96 } 96 }
97 } 97 }
98 98
99 public void UpdateAsset(AssetBase asset) 99 public void UpdateAsset(AssetBase asset)
100 { 100 {
101 throw new Exception("The method or operation is not implemented."); 101 throw new Exception("The method or operation is not implemented.");
102 } 102 }
103 103
104 public void StoreAndCommitAsset(AssetBase asset) 104 public void StoreAndCommitAsset(AssetBase asset)
105 { 105 {
106 try 106 try
107 { 107 {
108 MemoryStream s = new MemoryStream(); 108 MemoryStream s = new MemoryStream();
109 109
110 XmlSerializer xs = new XmlSerializer(typeof(AssetBase)); 110 XmlSerializer xs = new XmlSerializer(typeof(AssetBase));
111 xs.Serialize(s, asset); 111 xs.Serialize(s, asset);
112 RestClient rc = new RestClient(_assetServerUrl); 112 RestClient rc = new RestClient(_assetServerUrl);
113 rc.AddResourcePath("assets"); 113 rc.AddResourcePath("assets");
114 rc.RequestMethod = "POST"; 114 rc.RequestMethod = "POST";
115 rc.Request(s); 115 rc.Request(s);
116 } 116 }
117 catch (Exception e) 117 catch (Exception e)
118 { 118 {
119 MainLog.Instance.Error("ASSETS", e.Message); 119 MainLog.Instance.Error("ASSETS", e.Message);
120 } 120 }
121 } 121 }
122 122
123 public void Close() 123 public void Close()
124 { 124 {
125 throw new Exception("The method or operation is not implemented."); 125 throw new Exception("The method or operation is not implemented.");
126 } 126 }
127 127
128 public void LoadAsset(AssetBase info, bool image, string filename) 128 public void LoadAsset(AssetBase info, bool image, string filename)
129 { 129 {
130 throw new Exception("The method or operation is not implemented."); 130 throw new Exception("The method or operation is not implemented.");
131 } 131 }
132 132
133 public System.Collections.Generic.List<AssetBase> GetDefaultAssets() 133 public System.Collections.Generic.List<AssetBase> GetDefaultAssets()
134 { 134 {
135 throw new Exception("The method or operation is not implemented."); 135 throw new Exception("The method or operation is not implemented.");
136 } 136 }
137 137
138 public AssetBase CreateImageAsset(string assetIdStr, string name, string filename) 138 public AssetBase CreateImageAsset(string assetIdStr, string name, string filename)
139 { 139 {
140 throw new Exception("The method or operation is not implemented."); 140 throw new Exception("The method or operation is not implemented.");
141 } 141 }
142 142
143 public void ForEachDefaultAsset(Action<AssetBase> action) 143 public void ForEachDefaultAsset(Action<AssetBase> action)
144 { 144 {
145 throw new Exception("The method or operation is not implemented."); 145 throw new Exception("The method or operation is not implemented.");
146 } 146 }
147 147
148 public AssetBase CreateAsset(string assetIdStr, string name, string filename, bool isImage) 148 public AssetBase CreateAsset(string assetIdStr, string name, string filename, bool isImage)
149 { 149 {
150 throw new Exception("The method or operation is not implemented."); 150 throw new Exception("The method or operation is not implemented.");
151 } 151 }
152 152
153 public void ForEachXmlAsset(Action<AssetBase> action) 153 public void ForEachXmlAsset(Action<AssetBase> action)
154 { 154 {
155 throw new Exception("The method or operation is not implemented."); 155 throw new Exception("The method or operation is not implemented.");
156 } 156 }
157 157
158 #endregion 158 #endregion
159 } 159 }
160} 160}
diff --git a/OpenSim/Grid/AssetServer/RestService.cs b/OpenSim/Grid/AssetServer/RestService.cs
index 88a1668..e4f770d 100644
--- a/OpenSim/Grid/AssetServer/RestService.cs
+++ b/OpenSim/Grid/AssetServer/RestService.cs
@@ -1,109 +1,109 @@
1using System; 1using System;
2using System.IO; 2using System.IO;
3using System.Xml; 3using System.Xml;
4using System.Xml.Serialization; 4using System.Xml.Serialization;
5using System.Text; 5using System.Text;
6 6
7using libsecondlife; 7using libsecondlife;
8using OpenSim.Framework.Types; 8using OpenSim.Framework.Types;
9using OpenSim.Framework.Servers; 9using OpenSim.Framework.Servers;
10using OpenSim.Framework.Interfaces; 10using OpenSim.Framework.Interfaces;
11using OpenSim.Framework.Console; 11using OpenSim.Framework.Console;
12 12
13namespace OpenSim.Grid.AssetServer 13namespace OpenSim.Grid.AssetServer
14{ 14{
15 public class GetAssetStreamHandler : BaseStreamHandler 15 public class GetAssetStreamHandler : BaseStreamHandler
16 { 16 {
17 OpenAsset_Main m_assetManager; 17 OpenAsset_Main m_assetManager;
18 IAssetProvider m_assetProvider; 18 IAssetProvider m_assetProvider;
19 19
20 override public byte[] Handle(string path, Stream request) 20 override public byte[] Handle(string path, Stream request)
21 { 21 {
22 string param = GetParam(path); 22 string param = GetParam(path);
23 byte[] result = new byte[] { }; 23 byte[] result = new byte[] { };
24 try { 24 try {
25 25
26 string[] p = param.Split(new char[] { '/', '?', '&' }, StringSplitOptions.RemoveEmptyEntries); 26 string[] p = param.Split(new char[] { '/', '?', '&' }, StringSplitOptions.RemoveEmptyEntries);
27 27
28 if (p.Length > 0) 28 if (p.Length > 0)
29 { 29 {
30 LLUUID assetID; 30 LLUUID assetID;
31 bool isTexture = false; 31 bool isTexture = false;
32 LLUUID.TryParse(p[0], out assetID); 32 LLUUID.TryParse(p[0], out assetID);
33 if (p.Length > 1) 33 if (p.Length > 1)
34 { 34 {
35 if (string.Compare(p[1], "texture", true) == 0) 35 if (string.Compare(p[1], "texture", true) == 0)
36 isTexture = true; 36 isTexture = true;
37 } 37 }
38 38
39 39
40 AssetBase asset = m_assetProvider.FetchAsset(assetID); 40 AssetBase asset = m_assetProvider.FetchAsset(assetID);
41 if (asset != null) 41 if (asset != null)
42 { 42 {
43 MainLog.Instance.Debug("REST", "GET:/asset found {0}, {1}", assetID, asset.Name); 43 MainLog.Instance.Debug("REST", "GET:/asset found {0}, {1}", assetID, asset.Name);
44 44
45 XmlSerializer xs = new XmlSerializer(typeof(AssetBase)); 45 XmlSerializer xs = new XmlSerializer(typeof(AssetBase));
46 MemoryStream ms = new MemoryStream(); 46 MemoryStream ms = new MemoryStream();
47 XmlTextWriter xw = new XmlTextWriter(ms, Encoding.UTF8); 47 XmlTextWriter xw = new XmlTextWriter(ms, Encoding.UTF8);
48 xw.Formatting = Formatting.Indented; 48 xw.Formatting = Formatting.Indented;
49 xs.Serialize(xw, asset); 49 xs.Serialize(xw, asset);
50 xw.Flush(); 50 xw.Flush();
51 51
52 ms.Seek(0, SeekOrigin.Begin); 52 ms.Seek(0, SeekOrigin.Begin);
53 StreamReader sr = new StreamReader(ms); 53 StreamReader sr = new StreamReader(ms);
54 54
55 result = ms.GetBuffer(); 55 result = ms.GetBuffer();
56 Array.Resize<byte>(ref result, (int)ms.Length); 56 Array.Resize<byte>(ref result, (int)ms.Length);
57 } 57 }
58 else 58 else
59 { 59 {
60 MainLog.Instance.Verbose("REST", "GET:/asset failed to find {0}", assetID); 60 MainLog.Instance.Verbose("REST", "GET:/asset failed to find {0}", assetID);
61 } 61 }
62 } 62 }
63 } 63 }
64 catch (Exception e) 64 catch (Exception e)
65 { 65 {
66 MainLog.Instance.Error(e.ToString()); 66 MainLog.Instance.Error(e.ToString());
67 } 67 }
68 return result; 68 return result;
69 } 69 }
70 70
71 public GetAssetStreamHandler(OpenAsset_Main assetManager, IAssetProvider assetProvider) 71 public GetAssetStreamHandler(OpenAsset_Main assetManager, IAssetProvider assetProvider)
72 : base("GET", "/assets" ) 72 : base("GET", "/assets" )
73 { 73 {
74 m_assetManager = assetManager; 74 m_assetManager = assetManager;
75 m_assetProvider = assetProvider; 75 m_assetProvider = assetProvider;
76 } 76 }
77 } 77 }
78 78
79 public class PostAssetStreamHandler : BaseStreamHandler 79 public class PostAssetStreamHandler : BaseStreamHandler
80 { 80 {
81 OpenAsset_Main m_assetManager; 81 OpenAsset_Main m_assetManager;
82 IAssetProvider m_assetProvider; 82 IAssetProvider m_assetProvider;
83 83
84 override public byte[] Handle(string path, Stream request) 84 override public byte[] Handle(string path, Stream request)
85 { 85 {
86 string param = GetParam(path); 86 string param = GetParam(path);
87 87
88 LLUUID assetId; 88 LLUUID assetId;
89 if(param.Length > 0) 89 if(param.Length > 0)
90 LLUUID.TryParse(param, out assetId); 90 LLUUID.TryParse(param, out assetId);
91 byte[] txBuffer = new byte[4096]; 91 byte[] txBuffer = new byte[4096];
92 92
93 XmlSerializer xs = new XmlSerializer(typeof(AssetBase)); 93 XmlSerializer xs = new XmlSerializer(typeof(AssetBase));
94 AssetBase asset = (AssetBase)xs.Deserialize(request); 94 AssetBase asset = (AssetBase)xs.Deserialize(request);
95 95
96 MainLog.Instance.Verbose("REST", "StoreAndCommitAsset {0}", asset.FullID); 96 MainLog.Instance.Verbose("REST", "StoreAndCommitAsset {0}", asset.FullID);
97 m_assetProvider.CreateAsset(asset); 97 m_assetProvider.CreateAsset(asset);
98 98
99 return new byte[] { }; 99 return new byte[] { };
100 } 100 }
101 101
102 public PostAssetStreamHandler(OpenAsset_Main assetManager, IAssetProvider assetProvider) 102 public PostAssetStreamHandler(OpenAsset_Main assetManager, IAssetProvider assetProvider)
103 : base("POST", "/assets") 103 : base("POST", "/assets")
104 { 104 {
105 m_assetManager = assetManager; 105 m_assetManager = assetManager;
106 m_assetProvider = assetProvider; 106 m_assetProvider = assetProvider;
107 } 107 }
108 } 108 }
109} 109}
diff --git a/OpenSim/Region/Environment/Interfaces/IAvatarFactory.cs b/OpenSim/Region/Environment/Interfaces/IAvatarFactory.cs
index b6f24c3..28a5b4f 100644
--- a/OpenSim/Region/Environment/Interfaces/IAvatarFactory.cs
+++ b/OpenSim/Region/Environment/Interfaces/IAvatarFactory.cs
@@ -1,13 +1,13 @@
1using System; 1using System;
2using System.Collections.Generic; 2using System.Collections.Generic;
3using System.Text; 3using System.Text;
4using libsecondlife; 4using libsecondlife;
5using OpenSim.Framework.Types; 5using OpenSim.Framework.Types;
6 6
7namespace OpenSim.Region.Environment.Interfaces 7namespace OpenSim.Region.Environment.Interfaces
8{ 8{
9 public interface IAvatarFactory : IRegionModule 9 public interface IAvatarFactory : IRegionModule
10 { 10 {
11 bool TryGetIntialAvatarAppearance(LLUUID avatarId, out AvatarWearable[] wearables, out byte[] visualParams); 11 bool TryGetIntialAvatarAppearance(LLUUID avatarId, out AvatarWearable[] wearables, out byte[] visualParams);
12 } 12 }
13} 13}
diff --git a/OpenSim/Region/Environment/Modules/AvatarFactoryModule.cs b/OpenSim/Region/Environment/Modules/AvatarFactoryModule.cs
index f825b7a..cb8c758 100644
--- a/OpenSim/Region/Environment/Modules/AvatarFactoryModule.cs
+++ b/OpenSim/Region/Environment/Modules/AvatarFactoryModule.cs
@@ -1,57 +1,57 @@
1using System; 1using System;
2using System.Collections.Generic; 2using System.Collections.Generic;
3using System.Text; 3using System.Text;
4using libsecondlife; 4using libsecondlife;
5using Nini.Config; 5using Nini.Config;
6using OpenSim.Framework.Types; 6using OpenSim.Framework.Types;
7using OpenSim.Region.Environment.Interfaces; 7using OpenSim.Region.Environment.Interfaces;
8using OpenSim.Region.Environment.Scenes; 8using OpenSim.Region.Environment.Scenes;
9 9
10namespace OpenSim.Region.Environment.Modules 10namespace OpenSim.Region.Environment.Modules
11{ 11{
12 public class AvatarFactoryModule : IAvatarFactory 12 public class AvatarFactoryModule : IAvatarFactory
13 { 13 {
14 public bool TryGetIntialAvatarAppearance(LLUUID avatarId, out AvatarWearable[] wearables, out byte[] visualParams) 14 public bool TryGetIntialAvatarAppearance(LLUUID avatarId, out AvatarWearable[] wearables, out byte[] visualParams)
15 { 15 {
16 GetDefaultAvatarAppearance(out wearables, out visualParams); 16 GetDefaultAvatarAppearance(out wearables, out visualParams);
17 return true; 17 return true;
18 } 18 }
19 19
20 public void Initialise(Scene scene, IConfigSource source) 20 public void Initialise(Scene scene, IConfigSource source)
21 { 21 {
22 scene.RegisterModuleInterface<IAvatarFactory>(this); 22 scene.RegisterModuleInterface<IAvatarFactory>(this);
23 } 23 }
24 24
25 public void PostInitialise() 25 public void PostInitialise()
26 { 26 {
27 } 27 }
28 28
29 public void Close() 29 public void Close()
30 { 30 {
31 } 31 }
32 32
33 public string Name 33 public string Name
34 { 34 {
35 get { return "Default Avatar Factory"; } 35 get { return "Default Avatar Factory"; }
36 } 36 }
37 37
38 public bool IsSharedModule 38 public bool IsSharedModule
39 { 39 {
40 get { return true; } 40 get { return true; }
41 } 41 }
42 42
43 public static void GetDefaultAvatarAppearance(out AvatarWearable[] wearables, out byte[] visualParams) 43 public static void GetDefaultAvatarAppearance(out AvatarWearable[] wearables, out byte[] visualParams)
44 { 44 {
45 visualParams = new byte[218]; 45 visualParams = new byte[218];
46 for (int i = 0; i < 218; i++) 46 for (int i = 0; i < 218; i++)
47 { 47 {
48 visualParams[i] = 100; 48 visualParams[i] = 100;
49 } 49 }
50 50
51 wearables = AvatarWearable.DefaultWearables; 51 wearables = AvatarWearable.DefaultWearables;
52 } 52 }
53 } 53 }
54 54
55 55
56 56
57} 57}