MSSQLEstateData.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. /*
  2. * Copyright (c) Contributors, http://opensimulator.org/
  3. * See CONTRIBUTORS.TXT for a full list of copyright holders.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * * Neither the name of the OpenSimulator Project nor the
  13. * names of its contributors may be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
  17. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
  20. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  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
  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
  25. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. using System;
  28. using System.Collections.Generic;
  29. using System.Data;
  30. using System.Data.SqlClient;
  31. using System.Reflection;
  32. using log4net;
  33. using OpenMetaverse;
  34. using OpenSim.Framework;
  35. using OpenSim.Region.Framework.Interfaces;
  36. namespace OpenSim.Data.MSSQL
  37. {
  38. public class MSSQLEstateStore : IEstateDataStore
  39. {
  40. private const string _migrationStore = "EstateStore";
  41. private static readonly ILog _Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  42. private MSSQLManager _Database;
  43. private string m_connectionString;
  44. private FieldInfo[] _Fields;
  45. private Dictionary<string, FieldInfo> _FieldMap = new Dictionary<string, FieldInfo>();
  46. #region Public methods
  47. public MSSQLEstateStore()
  48. {
  49. }
  50. public MSSQLEstateStore(string connectionString)
  51. {
  52. Initialise(connectionString);
  53. }
  54. /// <summary>
  55. /// Initialises the estatedata class.
  56. /// </summary>
  57. /// <param name="connectionString">connectionString.</param>
  58. public void Initialise(string connectionString)
  59. {
  60. if (!string.IsNullOrEmpty(connectionString))
  61. {
  62. m_connectionString = connectionString;
  63. _Database = new MSSQLManager(connectionString);
  64. }
  65. //Migration settings
  66. _Database.CheckMigration(_migrationStore);
  67. //Interesting way to get parameters! Maybe implement that also with other types
  68. Type t = typeof(EstateSettings);
  69. _Fields = t.GetFields(BindingFlags.NonPublic |
  70. BindingFlags.Instance |
  71. BindingFlags.DeclaredOnly);
  72. foreach (FieldInfo f in _Fields)
  73. {
  74. if (f.Name.Substring(0, 2) == "m_")
  75. _FieldMap[f.Name.Substring(2)] = f;
  76. }
  77. }
  78. /// <summary>
  79. /// Loads the estate settings.
  80. /// </summary>
  81. /// <param name="regionID">region ID.</param>
  82. /// <returns></returns>
  83. public EstateSettings LoadEstateSettings(UUID regionID, bool create)
  84. {
  85. EstateSettings es = new EstateSettings();
  86. string sql = "select estate_settings." + String.Join(",estate_settings.", FieldList) + " from estate_map left join estate_settings on estate_map.EstateID = estate_settings.EstateID where estate_settings.EstateID is not null and RegionID = @RegionID";
  87. bool insertEstate = false;
  88. using (SqlConnection conn = new SqlConnection(m_connectionString))
  89. using (SqlCommand cmd = new SqlCommand(sql, conn))
  90. {
  91. cmd.Parameters.Add(_Database.CreateParameter("@RegionID", regionID));
  92. conn.Open();
  93. using (SqlDataReader reader = cmd.ExecuteReader())
  94. {
  95. if (reader.Read())
  96. {
  97. foreach (string name in FieldList)
  98. {
  99. FieldInfo f = _FieldMap[name];
  100. object v = reader[name];
  101. if (f.FieldType == typeof(bool) )
  102. {
  103. f.SetValue(es, Convert.ToInt32(v) != 0);
  104. }
  105. else if (f.FieldType == typeof(UUID) )
  106. {
  107. f.SetValue(es, new UUID((Guid)v)); // uuid);
  108. }
  109. else if (f.FieldType == typeof(string))
  110. {
  111. f.SetValue(es, v.ToString());
  112. }
  113. else if (f.FieldType == typeof(UInt32))
  114. {
  115. f.SetValue(es, Convert.ToUInt32(v));
  116. }
  117. else if (f.FieldType == typeof(Single))
  118. {
  119. f.SetValue(es, Convert.ToSingle(v));
  120. }
  121. else
  122. f.SetValue(es, v);
  123. }
  124. }
  125. else
  126. {
  127. insertEstate = true;
  128. }
  129. }
  130. }
  131. if (insertEstate && create)
  132. {
  133. List<string> names = new List<string>(FieldList);
  134. names.Remove("EstateID");
  135. sql = string.Format("insert into estate_settings ({0}) values ( @{1})", String.Join(",", names.ToArray()), String.Join(", @", names.ToArray()));
  136. //_Log.Debug("[DB ESTATE]: SQL: " + sql);
  137. using (SqlConnection conn = new SqlConnection(m_connectionString))
  138. using (SqlCommand insertCommand = new SqlCommand(sql, conn))
  139. {
  140. insertCommand.CommandText = sql + " SET @ID = SCOPE_IDENTITY()";
  141. foreach (string name in names)
  142. {
  143. insertCommand.Parameters.Add(_Database.CreateParameter("@" + name, _FieldMap[name].GetValue(es)));
  144. }
  145. SqlParameter idParameter = new SqlParameter("@ID", SqlDbType.Int);
  146. idParameter.Direction = ParameterDirection.Output;
  147. insertCommand.Parameters.Add(idParameter);
  148. conn.Open();
  149. insertCommand.ExecuteNonQuery();
  150. es.EstateID = Convert.ToUInt32(idParameter.Value);
  151. }
  152. sql = "INSERT INTO [estate_map] ([RegionID] ,[EstateID]) VALUES (@RegionID, @EstateID)";
  153. using (SqlConnection conn = new SqlConnection(m_connectionString))
  154. using (SqlCommand cmd = new SqlCommand(sql, conn))
  155. {
  156. cmd.Parameters.Add(_Database.CreateParameter("@RegionID", regionID));
  157. cmd.Parameters.Add(_Database.CreateParameter("@EstateID", es.EstateID));
  158. // This will throw on dupe key
  159. try
  160. {
  161. conn.Open();
  162. cmd.ExecuteNonQuery();
  163. }
  164. catch (Exception e)
  165. {
  166. _Log.DebugFormat("[ESTATE DB]: Error inserting regionID and EstateID in estate_map: {0}", e);
  167. }
  168. }
  169. //TODO check if this is needed??
  170. es.Save();
  171. }
  172. LoadBanList(es);
  173. es.EstateManagers = LoadUUIDList(es.EstateID, "estate_managers");
  174. es.EstateAccess = LoadUUIDList(es.EstateID, "estate_users");
  175. es.EstateGroups = LoadUUIDList(es.EstateID, "estate_groups");
  176. //Set event
  177. es.OnSave += StoreEstateSettings;
  178. return es;
  179. }
  180. /// <summary>
  181. /// Stores the estate settings.
  182. /// </summary>
  183. /// <param name="es">estate settings</param>
  184. public void StoreEstateSettings(EstateSettings es)
  185. {
  186. List<string> names = new List<string>(FieldList);
  187. names.Remove("EstateID");
  188. string sql = string.Format("UPDATE estate_settings SET ");
  189. foreach (string name in names)
  190. {
  191. sql += name + " = @" + name + ", ";
  192. }
  193. sql = sql.Remove(sql.LastIndexOf(","));
  194. sql += " WHERE EstateID = @EstateID";
  195. using (SqlConnection conn = new SqlConnection(m_connectionString))
  196. using (SqlCommand cmd = new SqlCommand(sql, conn))
  197. {
  198. foreach (string name in names)
  199. {
  200. cmd.Parameters.Add(_Database.CreateParameter("@" + name, _FieldMap[name].GetValue(es)));
  201. }
  202. cmd.Parameters.Add(_Database.CreateParameter("@EstateID", es.EstateID));
  203. conn.Open();
  204. cmd.ExecuteNonQuery();
  205. }
  206. SaveBanList(es);
  207. SaveUUIDList(es.EstateID, "estate_managers", es.EstateManagers);
  208. SaveUUIDList(es.EstateID, "estate_users", es.EstateAccess);
  209. SaveUUIDList(es.EstateID, "estate_groups", es.EstateGroups);
  210. }
  211. #endregion
  212. #region Private methods
  213. private string[] FieldList
  214. {
  215. get { return new List<string>(_FieldMap.Keys).ToArray(); }
  216. }
  217. private void LoadBanList(EstateSettings es)
  218. {
  219. es.ClearBans();
  220. string sql = "select bannedUUID from estateban where EstateID = @EstateID";
  221. using (SqlConnection conn = new SqlConnection(m_connectionString))
  222. using (SqlCommand cmd = new SqlCommand(sql, conn))
  223. {
  224. SqlParameter idParameter = new SqlParameter("@EstateID", SqlDbType.Int);
  225. idParameter.Value = es.EstateID;
  226. cmd.Parameters.Add(idParameter);
  227. conn.Open();
  228. using (SqlDataReader reader = cmd.ExecuteReader())
  229. {
  230. while (reader.Read())
  231. {
  232. EstateBan eb = new EstateBan();
  233. eb.BannedUserID = new UUID((Guid)reader["bannedUUID"]); //uuid;
  234. eb.BannedHostAddress = "0.0.0.0";
  235. eb.BannedHostIPMask = "0.0.0.0";
  236. es.AddBan(eb);
  237. }
  238. }
  239. }
  240. }
  241. private UUID[] LoadUUIDList(uint estateID, string table)
  242. {
  243. List<UUID> uuids = new List<UUID>();
  244. string sql = string.Format("select uuid from {0} where EstateID = @EstateID", table);
  245. using (SqlConnection conn = new SqlConnection(m_connectionString))
  246. using (SqlCommand cmd = new SqlCommand(sql, conn))
  247. {
  248. cmd.Parameters.Add(_Database.CreateParameter("@EstateID", estateID));
  249. conn.Open();
  250. using (SqlDataReader reader = cmd.ExecuteReader())
  251. {
  252. while (reader.Read())
  253. {
  254. uuids.Add(new UUID((Guid)reader["uuid"])); //uuid);
  255. }
  256. }
  257. }
  258. return uuids.ToArray();
  259. }
  260. private void SaveBanList(EstateSettings es)
  261. {
  262. //Delete first
  263. using (SqlConnection conn = new SqlConnection(m_connectionString))
  264. {
  265. conn.Open();
  266. using (SqlCommand cmd = conn.CreateCommand())
  267. {
  268. cmd.CommandText = "delete from estateban where EstateID = @EstateID";
  269. cmd.Parameters.AddWithValue("@EstateID", (int)es.EstateID);
  270. cmd.ExecuteNonQuery();
  271. //Insert after
  272. cmd.CommandText = "insert into estateban (EstateID, bannedUUID) values ( @EstateID, @bannedUUID )";
  273. cmd.Parameters.AddWithValue("@bannedUUID", Guid.Empty);
  274. foreach (EstateBan b in es.EstateBans)
  275. {
  276. cmd.Parameters["@bannedUUID"].Value = b.BannedUserID.Guid;
  277. cmd.ExecuteNonQuery();
  278. }
  279. }
  280. }
  281. }
  282. private void SaveUUIDList(uint estateID, string table, UUID[] data)
  283. {
  284. using (SqlConnection conn = new SqlConnection(m_connectionString))
  285. {
  286. conn.Open();
  287. using (SqlCommand cmd = conn.CreateCommand())
  288. {
  289. cmd.Parameters.AddWithValue("@EstateID", (int)estateID);
  290. cmd.CommandText = string.Format("delete from {0} where EstateID = @EstateID", table);
  291. cmd.ExecuteNonQuery();
  292. cmd.CommandText = string.Format("insert into {0} (EstateID, uuid) values ( @EstateID, @uuid )", table);
  293. cmd.Parameters.AddWithValue("@uuid", Guid.Empty);
  294. foreach (UUID uuid in data)
  295. {
  296. cmd.Parameters["@uuid"].Value = uuid.Guid; //.ToString(); //TODO check if this works
  297. cmd.ExecuteNonQuery();
  298. }
  299. }
  300. }
  301. }
  302. public EstateSettings LoadEstateSettings(int estateID)
  303. {
  304. // TODO: Implementation!
  305. return new EstateSettings();
  306. }
  307. public List<EstateSettings> LoadEstateSettingsAll()
  308. {
  309. // TODO: Implementation!
  310. return new List<EstateSettings>();
  311. }
  312. public List<int> GetEstates(string search)
  313. {
  314. // TODO: Implementation!
  315. return new List<int>();
  316. }
  317. public List<int> GetEstatesAll()
  318. {
  319. // TODO: Implementation!
  320. return new List<int>();
  321. }
  322. public List<int> GetEstatesByOwner(UUID ownerID)
  323. {
  324. return new List<int>();
  325. }
  326. public bool LinkRegion(UUID regionID, int estateID)
  327. {
  328. // TODO: Implementation!
  329. return false;
  330. }
  331. public List<UUID> GetRegions(int estateID)
  332. {
  333. // TODO: Implementation!
  334. return new List<UUID>();
  335. }
  336. public bool DeleteEstate(int estateID)
  337. {
  338. // TODO: Implementation!
  339. return false;
  340. }
  341. #endregion
  342. }
  343. }