clockwerk-opensim-stable – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 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  
28 using System;
29 using System.Collections;
30 using System.Collections.Generic;
31 using System.Collections.Specialized;
32 using System.Reflection;
33 using System.Threading;
34  
35 using Nwc.XmlRpc;
36  
37 using log4net;
38 using Mono.Addins;
39 using Nini.Config;
40  
41 using OpenMetaverse;
42 using OpenMetaverse.StructuredData;
43  
44 using OpenSim.Framework;
45 using OpenSim.Framework.Communications;
46 using OpenSim.Region.Framework.Interfaces;
47 using OpenSim.Services.Interfaces;
48  
49 /***************************************************************************
50 * Simian Data Map
51 * ===============
52 *
53 * OwnerID -> Type -> Key
54 * -----------------------
55 *
56 * UserID -> Group -> ActiveGroup
57 * + GroupID
58 *
59 * UserID -> GroupSessionDropped -> GroupID
60 * UserID -> GroupSessionInvited -> GroupID
61 *
62 * UserID -> GroupMember -> GroupID
63 * + SelectedRoleID [UUID]
64 * + AcceptNotices [bool]
65 * + ListInProfile [bool]
66 * + Contribution [int]
67 *
68 * UserID -> GroupRole[GroupID] -> RoleID
69 *
70 *
71 * GroupID -> Group -> GroupName
72 * + Charter
73 * + ShowInList
74 * + InsigniaID
75 * + MembershipFee
76 * + OpenEnrollment
77 * + AllowPublish
78 * + MaturePublish
79 * + FounderID
80 * + EveryonePowers
81 * + OwnerRoleID
82 * + OwnersPowers
83 *
84 * GroupID -> GroupRole -> RoleID
85 * + Name
86 * + Description
87 * + Title
88 * + Powers
89 *
90 * GroupID -> GroupMemberInvite -> InviteID
91 * + AgentID
92 * + RoleID
93 *
94 * GroupID -> GroupNotice -> NoticeID
95 * + TimeStamp [uint]
96 * + FromName [string]
97 * + Subject [string]
98 * + Message [string]
99 * + BinaryBucket [byte[]]
100 *
101 * */
102  
103 namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
104 {
105 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SimianGroupsServicesConnectorModule")]
106 public class SimianGroupsServicesConnectorModule : ISharedRegionModule, IGroupsServicesConnector
107 {
108 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
109  
110 public const GroupPowers m_DefaultEveryonePowers = GroupPowers.AllowSetHome |
111 GroupPowers.Accountable |
112 GroupPowers.JoinChat |
113 GroupPowers.AllowVoiceChat |
114 GroupPowers.ReceiveNotices |
115 GroupPowers.StartProposal |
116 GroupPowers.VoteOnProposal;
117  
118 // Would this be cleaner as (GroupPowers)ulong.MaxValue;
119 public const GroupPowers m_DefaultOwnerPowers = GroupPowers.Accountable
120 | GroupPowers.AllowEditLand
121 | GroupPowers.AllowFly
122 | GroupPowers.AllowLandmark
123 | GroupPowers.AllowRez
124 | GroupPowers.AllowSetHome
125 | GroupPowers.AllowVoiceChat
126 | GroupPowers.AssignMember
127 | GroupPowers.AssignMemberLimited
128 | GroupPowers.ChangeActions
129 | GroupPowers.ChangeIdentity
130 | GroupPowers.ChangeMedia
131 | GroupPowers.ChangeOptions
132 | GroupPowers.CreateRole
133 | GroupPowers.DeedObject
134 | GroupPowers.DeleteRole
135 | GroupPowers.Eject
136 | GroupPowers.FindPlaces
137 | GroupPowers.Invite
138 | GroupPowers.JoinChat
139 | GroupPowers.LandChangeIdentity
140 | GroupPowers.LandDeed
141 | GroupPowers.LandDivideJoin
142 | GroupPowers.LandEdit
143 | GroupPowers.LandEjectAndFreeze
144 | GroupPowers.LandGardening
145 | GroupPowers.LandManageAllowed
146 | GroupPowers.LandManageBanned
147 | GroupPowers.LandManagePasses
148 | GroupPowers.LandOptions
149 | GroupPowers.LandRelease
150 | GroupPowers.LandSetSale
151 | GroupPowers.ModerateChat
152 | GroupPowers.ObjectManipulate
153 | GroupPowers.ObjectSetForSale
154 | GroupPowers.ReceiveNotices
155 | GroupPowers.RemoveMember
156 | GroupPowers.ReturnGroupOwned
157 | GroupPowers.ReturnGroupSet
158 | GroupPowers.ReturnNonGroup
159 | GroupPowers.RoleProperties
160 | GroupPowers.SendNotices
161 | GroupPowers.SetLandingPoint
162 | GroupPowers.StartProposal
163 | GroupPowers.VoteOnProposal;
164  
165 private bool m_connectorEnabled = false;
166  
167 private string m_groupsServerURI = string.Empty;
168  
169 private bool m_debugEnabled = false;
170  
171 private Dictionary<string, bool> m_pendingRequests = new Dictionary<string,bool>();
172  
173 private ExpiringCache<string, OSDMap> m_memoryCache;
174 private int m_cacheTimeout = 30;
175  
176 // private IUserAccountService m_accountService = null;
177  
178  
179 #region Region Module interfaceBase Members
180  
181 public string Name
182 {
183 get { return "SimianGroupsServicesConnector"; }
184 }
185  
186 // this module is not intended to be replaced, but there should only be 1 of them.
187 public Type ReplaceableInterface
188 {
189 get { return null; }
190 }
191  
192 public void Initialise(IConfigSource config)
193 {
194 IConfig groupsConfig = config.Configs["Groups"];
195  
196 if (groupsConfig == null)
197 {
198 // Do not run this module by default.
199 return;
200 }
201 else
202 {
203 // if groups aren't enabled, we're not needed.
204 // if we're not specified as the connector to use, then we're not wanted
205 if ((groupsConfig.GetBoolean("Enabled", false) == false)
206 || (groupsConfig.GetString("ServicesConnectorModule", "XmlRpcGroupsServicesConnector") != Name))
207 {
208 m_connectorEnabled = false;
209 return;
210 }
211  
212 m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR]: Initializing {0}", this.Name);
213  
214 m_groupsServerURI = groupsConfig.GetString("GroupsServerURI", string.Empty);
215 if ((m_groupsServerURI == null) ||
216 (m_groupsServerURI == string.Empty))
217 {
218 m_log.ErrorFormat("Please specify a valid Simian Server for GroupsServerURI in OpenSim.ini, [Groups]");
219 m_connectorEnabled = false;
220 return;
221 }
222  
223  
224 m_cacheTimeout = groupsConfig.GetInt("GroupsCacheTimeout", 30);
225 if (m_cacheTimeout == 0)
226 {
227 m_log.WarnFormat("[SIMIAN-GROUPS-CONNECTOR] Groups Cache Disabled.");
228 }
229 else
230 {
231 m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Groups Cache Timeout set to {0}.", m_cacheTimeout);
232 }
233  
234  
235  
236 m_memoryCache = new ExpiringCache<string,OSDMap>();
237  
238  
239 // If we got all the config options we need, lets start'er'up
240 m_connectorEnabled = true;
241  
242 m_debugEnabled = groupsConfig.GetBoolean("DebugEnabled", true);
243  
244 }
245 }
246  
247 public void Close()
248 {
249 m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR]: Closing {0}", this.Name);
250 }
251  
252 public void AddRegion(OpenSim.Region.Framework.Scenes.Scene scene)
253 {
254 if (m_connectorEnabled)
255 {
256 scene.RegisterModuleInterface<IGroupsServicesConnector>(this);
257 }
258 }
259  
260 public void RemoveRegion(OpenSim.Region.Framework.Scenes.Scene scene)
261 {
262 if (scene.RequestModuleInterface<IGroupsServicesConnector>() == this)
263 {
264 scene.UnregisterModuleInterface<IGroupsServicesConnector>(this);
265 }
266 }
267  
268 public void RegionLoaded(OpenSim.Region.Framework.Scenes.Scene scene)
269 {
270 // TODO: May want to consider listenning for Agent Connections so we can pre-cache group info
271 // scene.EventManager.OnNewClient += OnNewClient;
272 }
273  
274 #endregion
275  
276 #region ISharedRegionModule Members
277  
278 public void PostInitialise()
279 {
280 // NoOp
281 }
282  
283 #endregion
284  
285  
286  
287  
288 #region IGroupsServicesConnector Members
289  
290 /// <summary>
291 /// Create a Group, including Everyone and Owners Role, place FounderID in both groups, select Owner as selected role, and newly created group as agent's active role.
292 /// </summary>
293 public UUID CreateGroup(UUID requestingAgentID, string name, string charter, bool showInList, UUID insigniaID,
294 int membershipFee, bool openEnrollment, bool allowPublish,
295 bool maturePublish, UUID founderID)
296 {
297 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
298  
299 UUID GroupID = UUID.Random();
300 UUID OwnerRoleID = UUID.Random();
301  
302 OSDMap GroupInfoMap = new OSDMap();
303 GroupInfoMap["Charter"] = OSD.FromString(charter);
304 GroupInfoMap["ShowInList"] = OSD.FromBoolean(showInList);
305 GroupInfoMap["InsigniaID"] = OSD.FromUUID(insigniaID);
306 GroupInfoMap["MembershipFee"] = OSD.FromInteger(0);
307 GroupInfoMap["OpenEnrollment"] = OSD.FromBoolean(openEnrollment);
308 GroupInfoMap["AllowPublish"] = OSD.FromBoolean(allowPublish);
309 GroupInfoMap["MaturePublish"] = OSD.FromBoolean(maturePublish);
310 GroupInfoMap["FounderID"] = OSD.FromUUID(founderID);
311 GroupInfoMap["EveryonePowers"] = OSD.FromULong((ulong)m_DefaultEveryonePowers);
312 GroupInfoMap["OwnerRoleID"] = OSD.FromUUID(OwnerRoleID);
313 GroupInfoMap["OwnersPowers"] = OSD.FromULong((ulong)m_DefaultOwnerPowers);
314  
315 if (SimianAddGeneric(GroupID, "Group", name, GroupInfoMap))
316 {
317 AddGroupRole(requestingAgentID, GroupID, UUID.Zero, "Everyone", "Members of " + name, "Member of " + name, (ulong)m_DefaultEveryonePowers);
318 AddGroupRole(requestingAgentID, GroupID, OwnerRoleID, "Owners", "Owners of " + name, "Owner of " + name, (ulong)m_DefaultOwnerPowers);
319  
320 AddAgentToGroup(requestingAgentID, requestingAgentID, GroupID, OwnerRoleID);
321  
322 return GroupID;
323 }
324 else
325 {
326 return UUID.Zero;
327 }
328 }
329  
330  
331 public void UpdateGroup(UUID requestingAgentID, UUID groupID, string charter, bool showInList,
332 UUID insigniaID, int membershipFee, bool openEnrollment,
333 bool allowPublish, bool maturePublish)
334 {
335 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
336 // TODO: Check to make sure requestingAgentID has permission to update group
337  
338 string GroupName;
339 OSDMap GroupInfoMap;
340 if (SimianGetFirstGenericEntry(groupID, "GroupInfo", out GroupName, out GroupInfoMap))
341 {
342 GroupInfoMap["Charter"] = OSD.FromString(charter);
343 GroupInfoMap["ShowInList"] = OSD.FromBoolean(showInList);
344 GroupInfoMap["InsigniaID"] = OSD.FromUUID(insigniaID);
345 GroupInfoMap["MembershipFee"] = OSD.FromInteger(0);
346 GroupInfoMap["OpenEnrollment"] = OSD.FromBoolean(openEnrollment);
347 GroupInfoMap["AllowPublish"] = OSD.FromBoolean(allowPublish);
348 GroupInfoMap["MaturePublish"] = OSD.FromBoolean(maturePublish);
349  
350 SimianAddGeneric(groupID, "Group", GroupName, GroupInfoMap);
351 }
352  
353 }
354  
355  
356 public void AddGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID, string name, string description,
357 string title, ulong powers)
358 {
359 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
360  
361 OSDMap GroupRoleInfo = new OSDMap();
362 GroupRoleInfo["Name"] = OSD.FromString(name);
363 GroupRoleInfo["Description"] = OSD.FromString(description);
364 GroupRoleInfo["Title"] = OSD.FromString(title);
365 GroupRoleInfo["Powers"] = OSD.FromULong((ulong)powers);
366  
367 // TODO: Add security, make sure that requestingAgentID has permision to add roles
368 SimianAddGeneric(groupID, "GroupRole", roleID.ToString(), GroupRoleInfo);
369 }
370  
371 public void RemoveGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID)
372 {
373 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
374  
375 // TODO: Add security
376  
377 // Can't delete the Everyone Role
378 if (roleID != UUID.Zero)
379 {
380 // Remove all GroupRole Members from Role
381 Dictionary<UUID, OSDMap> GroupRoleMembers;
382 string GroupRoleMemberType = "GroupRole" + groupID.ToString();
383 if (SimianGetGenericEntries(GroupRoleMemberType, roleID.ToString(), out GroupRoleMembers))
384 {
385 foreach (UUID UserID in GroupRoleMembers.Keys)
386 {
387 EnsureRoleNotSelectedByMember(groupID, roleID, UserID);
388  
389 SimianRemoveGenericEntry(UserID, GroupRoleMemberType, roleID.ToString());
390 }
391 }
392  
393 // Remove role
394 SimianRemoveGenericEntry(groupID, "GroupRole", roleID.ToString());
395 }
396 }
397  
398  
399 public void UpdateGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID, string name, string description,
400 string title, ulong powers)
401 {
402 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
403  
404 // TODO: Security, check that requestingAgentID is allowed to update group roles
405  
406 OSDMap GroupRoleInfo;
407 if (SimianGetGenericEntry(groupID, "GroupRole", roleID.ToString(), out GroupRoleInfo))
408 {
409 if (name != null)
410 {
411 GroupRoleInfo["Name"] = OSD.FromString(name);
412 }
413 if (description != null)
414 {
415 GroupRoleInfo["Description"] = OSD.FromString(description);
416 }
417 if (title != null)
418 {
419 GroupRoleInfo["Title"] = OSD.FromString(title);
420 }
421 GroupRoleInfo["Powers"] = OSD.FromULong((ulong)powers);
422  
423 }
424  
425  
426 SimianAddGeneric(groupID, "GroupRole", roleID.ToString(), GroupRoleInfo);
427 }
428  
429 public GroupRecord GetGroupRecord(UUID requestingAgentID, UUID groupID, string groupName)
430 {
431 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
432  
433 OSDMap GroupInfoMap = null;
434 if (groupID != UUID.Zero)
435 {
436 if (!SimianGetFirstGenericEntry(groupID, "Group", out groupName, out GroupInfoMap))
437 {
438 return null;
439 }
440 }
441 else if ((groupName != null) && (groupName != string.Empty))
442 {
443 if (!SimianGetFirstGenericEntry("Group", groupName, out groupID, out GroupInfoMap))
444 {
445 return null;
446 }
447 }
448  
449 GroupRecord GroupInfo = new GroupRecord();
450  
451 GroupInfo.GroupID = groupID;
452 GroupInfo.GroupName = groupName;
453 GroupInfo.Charter = GroupInfoMap["Charter"].AsString();
454 GroupInfo.ShowInList = GroupInfoMap["ShowInList"].AsBoolean();
455 GroupInfo.GroupPicture = GroupInfoMap["InsigniaID"].AsUUID();
456 GroupInfo.MembershipFee = GroupInfoMap["MembershipFee"].AsInteger();
457 GroupInfo.OpenEnrollment = GroupInfoMap["OpenEnrollment"].AsBoolean();
458 GroupInfo.AllowPublish = GroupInfoMap["AllowPublish"].AsBoolean();
459 GroupInfo.MaturePublish = GroupInfoMap["MaturePublish"].AsBoolean();
460 GroupInfo.FounderID = GroupInfoMap["FounderID"].AsUUID();
461 GroupInfo.OwnerRoleID = GroupInfoMap["OwnerRoleID"].AsUUID();
462  
463 return GroupInfo;
464  
465 }
466  
467 public GroupProfileData GetMemberGroupProfile(UUID requestingAgentID, UUID groupID, UUID memberID)
468 {
469 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
470  
471 OSDMap groupProfile;
472 string groupName;
473 if (!SimianGetFirstGenericEntry(groupID, "Group", out groupName, out groupProfile))
474 {
475 // GroupProfileData is not nullable
476 return new GroupProfileData();
477 }
478  
479 GroupProfileData MemberGroupProfile = new GroupProfileData();
480 MemberGroupProfile.GroupID = groupID;
481 MemberGroupProfile.Name = groupName;
482  
483 if (groupProfile["Charter"] != null)
484 {
485 MemberGroupProfile.Charter = groupProfile["Charter"].AsString();
486 }
487  
488 MemberGroupProfile.ShowInList = groupProfile["ShowInList"].AsString() == "1";
489 MemberGroupProfile.InsigniaID = groupProfile["InsigniaID"].AsUUID();
490 MemberGroupProfile.MembershipFee = groupProfile["MembershipFee"].AsInteger();
491 MemberGroupProfile.OpenEnrollment = groupProfile["OpenEnrollment"].AsBoolean();
492 MemberGroupProfile.AllowPublish = groupProfile["AllowPublish"].AsBoolean();
493 MemberGroupProfile.MaturePublish = groupProfile["MaturePublish"].AsBoolean();
494 MemberGroupProfile.FounderID = groupProfile["FounderID"].AsUUID();;
495 MemberGroupProfile.OwnerRole = groupProfile["OwnerRoleID"].AsUUID();
496  
497 Dictionary<UUID, OSDMap> Members;
498 if (SimianGetGenericEntries("GroupMember",groupID.ToString(), out Members))
499 {
500 MemberGroupProfile.GroupMembershipCount = Members.Count;
501 }
502  
503 Dictionary<string, OSDMap> Roles;
504 if (SimianGetGenericEntries(groupID, "GroupRole", out Roles))
505 {
506 MemberGroupProfile.GroupRolesCount = Roles.Count;
507 }
508  
509 // TODO: Get Group Money balance from somewhere
510 // group.Money = 0;
511  
512 GroupMembershipData MemberInfo = GetAgentGroupMembership(requestingAgentID, memberID, groupID);
513  
514 MemberGroupProfile.MemberTitle = MemberInfo.GroupTitle;
515 MemberGroupProfile.PowersMask = MemberInfo.GroupPowers;
516  
517 return MemberGroupProfile;
518 }
519  
520 public void SetAgentActiveGroup(UUID requestingAgentID, UUID agentID, UUID groupID)
521 {
522 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
523  
524 OSDMap ActiveGroup = new OSDMap();
525 ActiveGroup.Add("GroupID", OSD.FromUUID(groupID));
526 SimianAddGeneric(agentID, "Group", "ActiveGroup", ActiveGroup);
527 }
528  
529 public void SetAgentActiveGroupRole(UUID requestingAgentID, UUID agentID, UUID groupID, UUID roleID)
530 {
531 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
532  
533 OSDMap GroupMemberInfo;
534 if (!SimianGetGenericEntry(agentID, "GroupMember", groupID.ToString(), out GroupMemberInfo))
535 {
536 GroupMemberInfo = new OSDMap();
537 }
538  
539 GroupMemberInfo["SelectedRoleID"] = OSD.FromUUID(roleID);
540 SimianAddGeneric(agentID, "GroupMember", groupID.ToString(), GroupMemberInfo);
541 }
542  
543 public void SetAgentGroupInfo(UUID requestingAgentID, UUID agentID, UUID groupID, bool acceptNotices, bool listInProfile)
544 {
545 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
546  
547 OSDMap GroupMemberInfo;
548 if (!SimianGetGenericEntry(agentID, "GroupMember", groupID.ToString(), out GroupMemberInfo))
549 {
550 GroupMemberInfo = new OSDMap();
551 }
552  
553 GroupMemberInfo["AcceptNotices"] = OSD.FromBoolean(acceptNotices);
554 GroupMemberInfo["ListInProfile"] = OSD.FromBoolean(listInProfile);
555 GroupMemberInfo["Contribution"] = OSD.FromInteger(0);
556 GroupMemberInfo["SelectedRole"] = OSD.FromUUID(UUID.Zero);
557 SimianAddGeneric(agentID, "GroupMember", groupID.ToString(), GroupMemberInfo);
558 }
559  
560 public void AddAgentToGroupInvite(UUID requestingAgentID, UUID inviteID, UUID groupID, UUID roleID, UUID agentID)
561 {
562 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
563  
564 OSDMap Invite = new OSDMap();
565 Invite["AgentID"] = OSD.FromUUID(agentID);
566 Invite["RoleID"] = OSD.FromUUID(roleID);
567  
568 SimianAddGeneric(groupID, "GroupMemberInvite", inviteID.ToString(), Invite);
569 }
570  
571 public GroupInviteInfo GetAgentToGroupInvite(UUID requestingAgentID, UUID inviteID)
572 {
573 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
574  
575 OSDMap GroupMemberInvite;
576 UUID GroupID;
577 if (!SimianGetFirstGenericEntry("GroupMemberInvite", inviteID.ToString(), out GroupID, out GroupMemberInvite))
578 {
579 return null;
580 }
581  
582 GroupInviteInfo inviteInfo = new GroupInviteInfo();
583 inviteInfo.InviteID = inviteID;
584 inviteInfo.GroupID = GroupID;
585 inviteInfo.AgentID = GroupMemberInvite["AgentID"].AsUUID();
586 inviteInfo.RoleID = GroupMemberInvite["RoleID"].AsUUID();
587  
588 return inviteInfo;
589 }
590  
591 public void RemoveAgentToGroupInvite(UUID requestingAgentID, UUID inviteID)
592 {
593 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
594  
595 GroupInviteInfo invite = GetAgentToGroupInvite(requestingAgentID, inviteID);
596 SimianRemoveGenericEntry(invite.GroupID, "GroupMemberInvite", inviteID.ToString());
597 }
598  
599 public void AddAgentToGroup(UUID requestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID)
600 {
601 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
602  
603 // Setup Agent/Group information
604 SetAgentGroupInfo(requestingAgentID, AgentID, GroupID, true, true);
605  
606 // Add agent to Everyone Group
607 AddAgentToGroupRole(requestingAgentID, AgentID, GroupID, UUID.Zero);
608  
609 // Add agent to Specified Role
610 AddAgentToGroupRole(requestingAgentID, AgentID, GroupID, RoleID);
611  
612 // Set selected role in this group to specified role
613 SetAgentActiveGroupRole(requestingAgentID, AgentID, GroupID, RoleID);
614 }
615  
616 public void RemoveAgentFromGroup(UUID requestingAgentID, UUID agentID, UUID groupID)
617 {
618 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
619  
620 // If current active group is the group the agent is being removed from, change their group to UUID.Zero
621 GroupMembershipData memberActiveMembership = GetAgentActiveMembership(requestingAgentID, agentID);
622 if (memberActiveMembership.GroupID == groupID)
623 {
624 SetAgentActiveGroup(agentID, agentID, UUID.Zero);
625 }
626  
627 // Remove Group Member information for this group
628 SimianRemoveGenericEntry(agentID, "GroupMember", groupID.ToString());
629  
630 // By using a Simian Generics Type consisting of a prefix and a groupID,
631 // combined with RoleID as key allows us to get a list of roles a particular member
632 // of a group is assigned to.
633 string GroupRoleMemberType = "GroupRole" + groupID.ToString();
634  
635 // Take Agent out of all other group roles
636 Dictionary<string, OSDMap> GroupRoles;
637 if (SimianGetGenericEntries(agentID, GroupRoleMemberType, out GroupRoles))
638 {
639 foreach (string roleID in GroupRoles.Keys)
640 {
641 SimianRemoveGenericEntry(agentID, GroupRoleMemberType, roleID);
642 }
643 }
644 }
645  
646 public void AddAgentToGroupRole(UUID requestingAgentID, UUID agentID, UUID groupID, UUID roleID)
647 {
648 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
649  
650 SimianAddGeneric(agentID, "GroupRole" + groupID.ToString(), roleID.ToString(), new OSDMap());
651 }
652  
653 public void RemoveAgentFromGroupRole(UUID requestingAgentID, UUID agentID, UUID groupID, UUID roleID)
654 {
655 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
656  
657 // Cannot remove members from the Everyone Role
658 if (roleID != UUID.Zero)
659 {
660 EnsureRoleNotSelectedByMember(groupID, roleID, agentID);
661  
662 string GroupRoleMemberType = "GroupRole" + groupID.ToString();
663 SimianRemoveGenericEntry(agentID, GroupRoleMemberType, roleID.ToString());
664 }
665 }
666  
667 public List<DirGroupsReplyData> FindGroups(UUID requestingAgentID, string search)
668 {
669 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
670  
671 List<DirGroupsReplyData> findings = new List<DirGroupsReplyData>();
672  
673 NameValueCollection requestArgs = new NameValueCollection
674 {
675 { "RequestMethod", "GetGenerics" },
676 { "Type", "Group" },
677 { "Key", search },
678 { "Fuzzy", "1" }
679 };
680  
681  
682 OSDMap response = CachedPostRequest(requestArgs);
683 if (response["Success"].AsBoolean() && response["Entries"] is OSDArray)
684 {
685 OSDArray entryArray = (OSDArray)response["Entries"];
686 foreach (OSDMap entryMap in entryArray)
687 {
688 DirGroupsReplyData data = new DirGroupsReplyData();
689 data.groupID = entryMap["OwnerID"].AsUUID();
690 data.groupName = entryMap["Key"].AsString();
691  
692 // TODO: is there a better way to do this?
693 Dictionary<UUID, OSDMap> Members;
694 if (SimianGetGenericEntries("GroupMember", data.groupID.ToString(), out Members))
695 {
696 data.members = Members.Count;
697 }
698 else
699 {
700 data.members = 0;
701 }
702  
703 // TODO: sort results?
704 // data.searchOrder = order;
705  
706 findings.Add(data);
707 }
708 }
709  
710 return findings;
711 }
712  
713 public GroupMembershipData GetAgentGroupMembership(UUID requestingAgentID, UUID agentID, UUID groupID)
714 {
715 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
716  
717 GroupMembershipData data = null;
718 // bool foundData = false;
719  
720 OSDMap UserGroupMemberInfo;
721 if (SimianGetGenericEntry(agentID, "GroupMember", groupID.ToString(), out UserGroupMemberInfo))
722 {
723 data = new GroupMembershipData();
724 data.AcceptNotices = UserGroupMemberInfo["AcceptNotices"].AsBoolean();
725 data.Contribution = UserGroupMemberInfo["Contribution"].AsInteger();
726 data.ListInProfile = UserGroupMemberInfo["ListInProfile"].AsBoolean();
727 data.ActiveRole = UserGroupMemberInfo["SelectedRoleID"].AsUUID();
728  
729 ///////////////////////////////
730 // Agent Specific Information:
731 //
732 OSDMap UserActiveGroup;
733 if (SimianGetGenericEntry(agentID, "Group", "ActiveGroup", out UserActiveGroup))
734 {
735 data.Active = UserActiveGroup["GroupID"].AsUUID().Equals(groupID);
736 }
737  
738 ///////////////////////////////
739 // Role Specific Information:
740 //
741 OSDMap GroupRoleInfo;
742 if (SimianGetGenericEntry(groupID, "GroupRole", data.ActiveRole.ToString(), out GroupRoleInfo))
743 {
744 data.GroupTitle = GroupRoleInfo["Title"].AsString();
745 data.GroupPowers = GroupRoleInfo["Powers"].AsULong();
746 }
747  
748 ///////////////////////////////
749 // Group Specific Information:
750 //
751 OSDMap GroupInfo;
752 string GroupName;
753 if (SimianGetFirstGenericEntry(groupID, "Group", out GroupName, out GroupInfo))
754 {
755 data.GroupID = groupID;
756 data.AllowPublish = GroupInfo["AllowPublish"].AsBoolean();
757 data.Charter = GroupInfo["Charter"].AsString();
758 data.FounderID = GroupInfo["FounderID"].AsUUID();
759 data.GroupName = GroupName;
760 data.GroupPicture = GroupInfo["InsigniaID"].AsUUID();
761 data.MaturePublish = GroupInfo["MaturePublish"].AsBoolean();
762 data.MembershipFee = GroupInfo["MembershipFee"].AsInteger();
763 data.OpenEnrollment = GroupInfo["OpenEnrollment"].AsBoolean();
764 data.ShowInList = GroupInfo["ShowInList"].AsBoolean();
765 }
766 }
767  
768 return data;
769 }
770  
771 public GroupMembershipData GetAgentActiveMembership(UUID requestingAgentID, UUID agentID)
772 {
773 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
774  
775 UUID GroupID = UUID.Zero;
776 OSDMap UserActiveGroup;
777 if (SimianGetGenericEntry(agentID, "Group", "ActiveGroup", out UserActiveGroup))
778 {
779 GroupID = UserActiveGroup["GroupID"].AsUUID();
780 }
781  
782 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Active GroupID : {0}", GroupID.ToString());
783 return GetAgentGroupMembership(requestingAgentID, agentID, GroupID);
784 }
785  
786 public List<GroupMembershipData> GetAgentGroupMemberships(UUID requestingAgentID, UUID agentID)
787 {
788 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
789  
790 List<GroupMembershipData> memberships = new List<GroupMembershipData>();
791  
792 Dictionary<string,OSDMap> GroupMemberShips;
793 if (SimianGetGenericEntries(agentID, "GroupMember", out GroupMemberShips))
794 {
795 foreach (string key in GroupMemberShips.Keys)
796 {
797 memberships.Add(GetAgentGroupMembership(requestingAgentID, agentID, UUID.Parse(key)));
798 }
799 }
800  
801 return memberships;
802 }
803  
804 public List<GroupRolesData> GetAgentGroupRoles(UUID requestingAgentID, UUID agentID, UUID groupID)
805 {
806 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
807  
808 List<GroupRolesData> Roles = new List<GroupRolesData>();
809  
810 Dictionary<string, OSDMap> GroupRoles;
811 if (SimianGetGenericEntries(groupID, "GroupRole", out GroupRoles))
812 {
813 Dictionary<string, OSDMap> MemberRoles;
814 if (SimianGetGenericEntries(agentID, "GroupRole" + groupID.ToString(), out MemberRoles))
815 {
816 foreach (KeyValuePair<string, OSDMap> kvp in MemberRoles)
817 {
818 GroupRolesData data = new GroupRolesData();
819 data.RoleID = UUID.Parse(kvp.Key);
820 data.Name = GroupRoles[kvp.Key]["Name"].AsString();
821 data.Description = GroupRoles[kvp.Key]["Description"].AsString();
822 data.Title = GroupRoles[kvp.Key]["Title"].AsString();
823 data.Powers = GroupRoles[kvp.Key]["Powers"].AsULong();
824  
825 Roles.Add(data);
826 }
827 }
828 }
829 return Roles;
830 }
831  
832 public List<GroupRolesData> GetGroupRoles(UUID requestingAgentID, UUID groupID)
833 {
834 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
835  
836 List<GroupRolesData> Roles = new List<GroupRolesData>();
837  
838 Dictionary<string, OSDMap> GroupRoles;
839 if (SimianGetGenericEntries(groupID, "GroupRole", out GroupRoles))
840 {
841 foreach (KeyValuePair<string, OSDMap> role in GroupRoles)
842 {
843 GroupRolesData data = new GroupRolesData();
844  
845 data.RoleID = UUID.Parse(role.Key);
846  
847 data.Name = role.Value["Name"].AsString();
848 data.Description = role.Value["Description"].AsString();
849 data.Title = role.Value["Title"].AsString();
850 data.Powers = role.Value["Powers"].AsULong();
851  
852 Dictionary<UUID, OSDMap> GroupRoleMembers;
853 if (SimianGetGenericEntries("GroupRole" + groupID.ToString(), role.Key, out GroupRoleMembers))
854 {
855 data.Members = GroupRoleMembers.Count;
856 }
857 else
858 {
859 data.Members = 0;
860 }
861  
862 Roles.Add(data);
863 }
864 }
865  
866 return Roles;
867  
868 }
869  
870  
871  
872 public List<GroupMembersData> GetGroupMembers(UUID requestingAgentID, UUID GroupID)
873 {
874 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
875  
876 List<GroupMembersData> members = new List<GroupMembersData>();
877  
878 OSDMap GroupInfo;
879 string GroupName;
880 UUID GroupOwnerRoleID = UUID.Zero;
881 if (!SimianGetFirstGenericEntry(GroupID, "Group", out GroupName, out GroupInfo))
882 {
883 return members;
884 }
885 GroupOwnerRoleID = GroupInfo["OwnerRoleID"].AsUUID();
886  
887 // Locally cache group roles, since we'll be needing this data for each member
888 Dictionary<string,OSDMap> GroupRoles;
889 SimianGetGenericEntries(GroupID, "GroupRole", out GroupRoles);
890  
891 // Locally cache list of group owners
892 Dictionary<UUID, OSDMap> GroupOwners;
893 SimianGetGenericEntries("GroupRole" + GroupID.ToString(), GroupOwnerRoleID.ToString(), out GroupOwners);
894  
895  
896 Dictionary<UUID, OSDMap> GroupMembers;
897 if (SimianGetGenericEntries("GroupMember", GroupID.ToString(), out GroupMembers))
898 {
899 foreach (KeyValuePair<UUID, OSDMap> member in GroupMembers)
900 {
901 GroupMembersData data = new GroupMembersData();
902  
903 data.AgentID = member.Key;
904  
905 UUID SelectedRoleID = member.Value["SelectedRoleID"].AsUUID();
906  
907 data.AcceptNotices = member.Value["AcceptNotices"].AsBoolean();
908 data.ListInProfile = member.Value["ListInProfile"].AsBoolean();
909 data.Contribution = member.Value["Contribution"].AsInteger();
910  
911 data.IsOwner = GroupOwners.ContainsKey(member.Key);
912  
913 OSDMap GroupRoleInfo = GroupRoles[SelectedRoleID.ToString()];
914 data.Title = GroupRoleInfo["Title"].AsString();
915 data.AgentPowers = GroupRoleInfo["Powers"].AsULong();
916  
917 members.Add(data);
918 }
919 }
920  
921 return members;
922  
923 }
924  
925 public List<GroupRoleMembersData> GetGroupRoleMembers(UUID requestingAgentID, UUID groupID)
926 {
927 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
928  
929 List<GroupRoleMembersData> members = new List<GroupRoleMembersData>();
930  
931 Dictionary<string, OSDMap> GroupRoles;
932 if (SimianGetGenericEntries(groupID, "GroupRole", out GroupRoles))
933 {
934 foreach (KeyValuePair<string, OSDMap> Role in GroupRoles)
935 {
936 Dictionary<UUID, OSDMap> GroupRoleMembers;
937 if (SimianGetGenericEntries("GroupRole"+groupID.ToString(), Role.Key, out GroupRoleMembers))
938 {
939 foreach (KeyValuePair<UUID, OSDMap> GroupRoleMember in GroupRoleMembers)
940 {
941 GroupRoleMembersData data = new GroupRoleMembersData();
942  
943 data.MemberID = GroupRoleMember.Key;
944 data.RoleID = UUID.Parse(Role.Key);
945  
946 members.Add(data);
947 }
948 }
949 }
950 }
951  
952 return members;
953 }
954  
955 public List<GroupNoticeData> GetGroupNotices(UUID requestingAgentID, UUID GroupID)
956 {
957 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
958  
959 List<GroupNoticeData> values = new List<GroupNoticeData>();
960  
961 Dictionary<string, OSDMap> Notices;
962 if (SimianGetGenericEntries(GroupID, "GroupNotice", out Notices))
963 {
964 foreach (KeyValuePair<string, OSDMap> Notice in Notices)
965 {
966 GroupNoticeData data = new GroupNoticeData();
967 data.NoticeID = UUID.Parse(Notice.Key);
968 data.Timestamp = Notice.Value["TimeStamp"].AsUInteger();
969 data.FromName = Notice.Value["FromName"].AsString();
970 data.Subject = Notice.Value["Subject"].AsString();
971 data.HasAttachment = Notice.Value["BinaryBucket"].AsBinary().Length > 0;
972  
973 //TODO: Figure out how to get this
974 data.AssetType = 0;
975  
976 values.Add(data);
977 }
978 }
979  
980 return values;
981  
982 }
983 public GroupNoticeInfo GetGroupNotice(UUID requestingAgentID, UUID noticeID)
984 {
985 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
986  
987 OSDMap GroupNotice;
988 UUID GroupID;
989 if (SimianGetFirstGenericEntry("GroupNotice", noticeID.ToString(), out GroupID, out GroupNotice))
990 {
991 GroupNoticeInfo data = new GroupNoticeInfo();
992 data.GroupID = GroupID;
993 data.Message = GroupNotice["Message"].AsString();
994 data.BinaryBucket = GroupNotice["BinaryBucket"].AsBinary();
995 data.noticeData.NoticeID = noticeID;
996 data.noticeData.Timestamp = GroupNotice["TimeStamp"].AsUInteger();
997 data.noticeData.FromName = GroupNotice["FromName"].AsString();
998 data.noticeData.Subject = GroupNotice["Subject"].AsString();
999 data.noticeData.HasAttachment = data.BinaryBucket.Length > 0;
1000 data.noticeData.AssetType = 0;
1001  
1002 if (data.Message == null)
1003 {
1004 data.Message = string.Empty;
1005 }
1006  
1007 return data;
1008 }
1009 return null;
1010 }
1011 public void AddGroupNotice(UUID requestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, byte[] binaryBucket)
1012 {
1013 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
1014  
1015 OSDMap Notice = new OSDMap();
1016 Notice["TimeStamp"] = OSD.FromUInteger((uint)Util.UnixTimeSinceEpoch());
1017 Notice["FromName"] = OSD.FromString(fromName);
1018 Notice["Subject"] = OSD.FromString(subject);
1019 Notice["Message"] = OSD.FromString(message);
1020 Notice["BinaryBucket"] = OSD.FromBinary(binaryBucket);
1021  
1022 SimianAddGeneric(groupID, "GroupNotice", noticeID.ToString(), Notice);
1023  
1024 }
1025 #endregion
1026  
1027 #region GroupSessionTracking
1028  
1029 public void ResetAgentGroupChatSessions(UUID agentID)
1030 {
1031 Dictionary<string, OSDMap> agentSessions;
1032  
1033 if (SimianGetGenericEntries(agentID, "GroupSessionDropped", out agentSessions))
1034 {
1035 foreach (string GroupID in agentSessions.Keys)
1036 {
1037 SimianRemoveGenericEntry(agentID, "GroupSessionDropped", GroupID);
1038 }
1039 }
1040  
1041 if (SimianGetGenericEntries(agentID, "GroupSessionInvited", out agentSessions))
1042 {
1043 foreach (string GroupID in agentSessions.Keys)
1044 {
1045 SimianRemoveGenericEntry(agentID, "GroupSessionInvited", GroupID);
1046 }
1047 }
1048 }
1049  
1050 public bool hasAgentDroppedGroupChatSession(UUID agentID, UUID groupID)
1051 {
1052 OSDMap session;
1053 return SimianGetGenericEntry(agentID, "GroupSessionDropped", groupID.ToString(), out session);
1054 }
1055  
1056 public void AgentDroppedFromGroupChatSession(UUID agentID, UUID groupID)
1057 {
1058 SimianAddGeneric(agentID, "GroupSessionDropped", groupID.ToString(), new OSDMap());
1059 }
1060  
1061 public void AgentInvitedToGroupChatSession(UUID agentID, UUID groupID)
1062 {
1063 SimianAddGeneric(agentID, "GroupSessionInvited", groupID.ToString(), new OSDMap());
1064 }
1065  
1066 public bool hasAgentBeenInvitedToGroupChatSession(UUID agentID, UUID groupID)
1067 {
1068 OSDMap session;
1069 return SimianGetGenericEntry(agentID, "GroupSessionDropped", groupID.ToString(), out session);
1070 }
1071  
1072 #endregion
1073  
1074 private void EnsureRoleNotSelectedByMember(UUID groupID, UUID roleID, UUID userID)
1075 {
1076 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
1077  
1078 // If member's SelectedRole is roleID, change their selected role to Everyone
1079 // before removing them from the role
1080 OSDMap UserGroupInfo;
1081 if (SimianGetGenericEntry(userID, "GroupMember", groupID.ToString(), out UserGroupInfo))
1082 {
1083 if (UserGroupInfo["SelectedRoleID"].AsUUID() == roleID)
1084 {
1085 UserGroupInfo["SelectedRoleID"] = OSD.FromUUID(UUID.Zero);
1086 }
1087 SimianAddGeneric(userID, "GroupMember", groupID.ToString(), UserGroupInfo);
1088 }
1089 }
1090  
1091  
1092 #region Simian Util Methods
1093 private bool SimianAddGeneric(UUID ownerID, string type, string key, OSDMap map)
1094 {
1095 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2},{3})", System.Reflection.MethodBase.GetCurrentMethod().Name, ownerID, type, key);
1096  
1097 string value = OSDParser.SerializeJsonString(map);
1098  
1099 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] value: {0}", value);
1100  
1101 NameValueCollection RequestArgs = new NameValueCollection
1102 {
1103 { "RequestMethod", "AddGeneric" },
1104 { "OwnerID", ownerID.ToString() },
1105 { "Type", type },
1106 { "Key", key },
1107 { "Value", value}
1108 };
1109  
1110  
1111 OSDMap Response = CachedPostRequest(RequestArgs);
1112 if (Response["Success"].AsBoolean())
1113 {
1114 return true;
1115 }
1116 else
1117 {
1118 m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: Error {0}, {1}, {2}, {3}", ownerID, type, key, Response["Message"]);
1119 return false;
1120 }
1121 }
1122  
1123 /// <summary>
1124 /// Returns the first of possibly many entries for Owner/Type pair
1125 /// </summary>
1126 private bool SimianGetFirstGenericEntry(UUID ownerID, string type, out string key, out OSDMap map)
1127 {
1128 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2})", System.Reflection.MethodBase.GetCurrentMethod().Name, ownerID, type);
1129  
1130 NameValueCollection RequestArgs = new NameValueCollection
1131 {
1132 { "RequestMethod", "GetGenerics" },
1133 { "OwnerID", ownerID.ToString() },
1134 { "Type", type }
1135 };
1136  
1137  
1138 OSDMap Response = CachedPostRequest(RequestArgs);
1139 if (Response["Success"].AsBoolean() && Response["Entries"] is OSDArray)
1140 {
1141 OSDArray entryArray = (OSDArray)Response["Entries"];
1142 if (entryArray.Count >= 1)
1143 {
1144 OSDMap entryMap = entryArray[0] as OSDMap;
1145 key = entryMap["Key"].AsString();
1146 map = (OSDMap)OSDParser.DeserializeJson(entryMap["Value"].AsString());
1147  
1148 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Generics Result {0}", entryMap["Value"].AsString());
1149  
1150 return true;
1151 }
1152 else
1153 {
1154 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] No Generics Results");
1155 }
1156 }
1157 else
1158 {
1159 m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: Error retrieving group info ({0})", Response["Message"]);
1160 }
1161 key = null;
1162 map = null;
1163 return false;
1164 }
1165 private bool SimianGetFirstGenericEntry(string type, string key, out UUID ownerID, out OSDMap map)
1166 {
1167 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2})", System.Reflection.MethodBase.GetCurrentMethod().Name, type, key);
1168  
1169  
1170 NameValueCollection RequestArgs = new NameValueCollection
1171 {
1172 { "RequestMethod", "GetGenerics" },
1173 { "Type", type },
1174 { "Key", key}
1175 };
1176  
1177  
1178 OSDMap Response = CachedPostRequest(RequestArgs);
1179 if (Response["Success"].AsBoolean() && Response["Entries"] is OSDArray)
1180 {
1181 OSDArray entryArray = (OSDArray)Response["Entries"];
1182 if (entryArray.Count >= 1)
1183 {
1184 OSDMap entryMap = entryArray[0] as OSDMap;
1185 ownerID = entryMap["OwnerID"].AsUUID();
1186 map = (OSDMap)OSDParser.DeserializeJson(entryMap["Value"].AsString());
1187  
1188 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Generics Result {0}", entryMap["Value"].AsString());
1189  
1190 return true;
1191 }
1192 else
1193 {
1194 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] No Generics Results");
1195 }
1196 }
1197 else
1198 {
1199 m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: Error retrieving group info ({0})", Response["Message"]);
1200 }
1201 ownerID = UUID.Zero;
1202 map = null;
1203 return false;
1204 }
1205  
1206 private bool SimianGetGenericEntry(UUID ownerID, string type, string key, out OSDMap map)
1207 {
1208 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2},{3})", System.Reflection.MethodBase.GetCurrentMethod().Name, ownerID, type, key);
1209  
1210 NameValueCollection RequestArgs = new NameValueCollection
1211 {
1212 { "RequestMethod", "GetGenerics" },
1213 { "OwnerID", ownerID.ToString() },
1214 { "Type", type },
1215 { "Key", key}
1216 };
1217  
1218  
1219 OSDMap Response = CachedPostRequest(RequestArgs);
1220 if (Response["Success"].AsBoolean() && Response["Entries"] is OSDArray)
1221 {
1222 OSDArray entryArray = (OSDArray)Response["Entries"];
1223 if (entryArray.Count == 1)
1224 {
1225 OSDMap entryMap = entryArray[0] as OSDMap;
1226 key = entryMap["Key"].AsString();
1227 map = (OSDMap)OSDParser.DeserializeJson(entryMap["Value"].AsString());
1228  
1229 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Generics Result {0}", entryMap["Value"].AsString());
1230  
1231 return true;
1232 }
1233 else
1234 {
1235 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] No Generics Results");
1236 }
1237 }
1238 else
1239 {
1240 m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: Error retrieving group info ({0})", Response["Message"]);
1241 }
1242 map = null;
1243 return false;
1244 }
1245  
1246 private bool SimianGetGenericEntries(UUID ownerID, string type, out Dictionary<string, OSDMap> maps)
1247 {
1248 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2})", System.Reflection.MethodBase.GetCurrentMethod().Name,ownerID, type);
1249  
1250 NameValueCollection requestArgs = new NameValueCollection
1251 {
1252 { "RequestMethod", "GetGenerics" },
1253 { "OwnerID", ownerID.ToString() },
1254 { "Type", type }
1255 };
1256  
1257  
1258  
1259 OSDMap response = CachedPostRequest(requestArgs);
1260 if (response["Success"].AsBoolean() && response["Entries"] is OSDArray)
1261 {
1262 maps = new Dictionary<string, OSDMap>();
1263  
1264 OSDArray entryArray = (OSDArray)response["Entries"];
1265 foreach (OSDMap entryMap in entryArray)
1266 {
1267 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Generics Result {0}", entryMap["Value"].AsString());
1268 maps.Add(entryMap["Key"].AsString(), (OSDMap)OSDParser.DeserializeJson(entryMap["Value"].AsString()));
1269 }
1270 if (maps.Count == 0)
1271 {
1272 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] No Generics Results");
1273 }
1274  
1275 return true;
1276 }
1277 else
1278 {
1279 maps = null;
1280 m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: Error retrieving group info ({0})", response["Message"]);
1281 }
1282 return false;
1283 }
1284 private bool SimianGetGenericEntries(string type, string key, out Dictionary<UUID, OSDMap> maps)
1285 {
1286 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2})", System.Reflection.MethodBase.GetCurrentMethod().Name, type, key);
1287  
1288 NameValueCollection requestArgs = new NameValueCollection
1289 {
1290 { "RequestMethod", "GetGenerics" },
1291 { "Type", type },
1292 { "Key", key }
1293 };
1294  
1295  
1296  
1297 OSDMap response = CachedPostRequest(requestArgs);
1298 if (response["Success"].AsBoolean() && response["Entries"] is OSDArray)
1299 {
1300 maps = new Dictionary<UUID, OSDMap>();
1301  
1302 OSDArray entryArray = (OSDArray)response["Entries"];
1303 foreach (OSDMap entryMap in entryArray)
1304 {
1305 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Generics Result {0}", entryMap["Value"].AsString());
1306 maps.Add(entryMap["OwnerID"].AsUUID(), (OSDMap)OSDParser.DeserializeJson(entryMap["Value"].AsString()));
1307 }
1308 if (maps.Count == 0)
1309 {
1310 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] No Generics Results");
1311 }
1312 return true;
1313 }
1314 else
1315 {
1316 maps = null;
1317 m_log.WarnFormat("[SIMIAN-GROUPS-CONNECTOR]: Error retrieving group info ({0})", response["Message"]);
1318 }
1319 return false;
1320 }
1321  
1322 private bool SimianRemoveGenericEntry(UUID ownerID, string type, string key)
1323 {
1324 if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2},{3})", System.Reflection.MethodBase.GetCurrentMethod().Name, ownerID, type, key);
1325  
1326 NameValueCollection requestArgs = new NameValueCollection
1327 {
1328 { "RequestMethod", "RemoveGeneric" },
1329 { "OwnerID", ownerID.ToString() },
1330 { "Type", type },
1331 { "Key", key }
1332 };
1333  
1334  
1335 OSDMap response = CachedPostRequest(requestArgs);
1336 if (response["Success"].AsBoolean())
1337 {
1338 return true;
1339 }
1340 else
1341 {
1342 m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: Error {0}, {1}, {2}, {3}", ownerID, type, key, response["Message"]);
1343 return false;
1344 }
1345 }
1346 #endregion
1347  
1348 #region CheesyCache
1349 OSDMap CachedPostRequest(NameValueCollection requestArgs)
1350 {
1351 // Immediately forward the request if the cache is disabled.
1352 if (m_cacheTimeout == 0)
1353 {
1354 m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: cache is disabled");
1355 return WebUtil.PostToService(m_groupsServerURI, requestArgs);
1356 }
1357  
1358 // Check if this is an update or a request
1359 if (requestArgs["RequestMethod"] == "RemoveGeneric"
1360 || requestArgs["RequestMethod"] == "AddGeneric")
1361 {
1362 m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: clearing generics cache");
1363  
1364 // Any and all updates cause the cache to clear
1365 m_memoryCache.Clear();
1366  
1367 // Send update to server, return the response without caching it
1368 return WebUtil.PostToService(m_groupsServerURI, requestArgs);
1369 }
1370  
1371 // If we're not doing an update, we must be requesting data
1372  
1373 // Create the cache key for the request and see if we have it cached
1374 string CacheKey = WebUtil.BuildQueryString(requestArgs);
1375  
1376 // This code uses a leader/follower pattern. On a cache miss, the request is added
1377 // to a queue; the first thread to add it to the queue completes the request while
1378 // follow on threads busy wait for the results, this situation seems to happen
1379 // often when checking permissions
1380 while (true)
1381 {
1382 OSDMap response = null;
1383 bool firstRequest = false;
1384  
1385 lock (m_memoryCache)
1386 {
1387 if (m_memoryCache.TryGetValue(CacheKey, out response))
1388 return response;
1389  
1390 if (! m_pendingRequests.ContainsKey(CacheKey))
1391 {
1392 m_pendingRequests.Add(CacheKey,true);
1393 firstRequest = true;
1394 }
1395 }
1396  
1397 if (firstRequest)
1398 {
1399 // if it wasn't in the cache, pass the request to the Simian Grid Services
1400 try
1401 {
1402 response = WebUtil.PostToService(m_groupsServerURI, requestArgs);
1403 }
1404 catch (Exception)
1405 {
1406 m_log.ErrorFormat("[SIMIAN GROUPS CONNECTOR]: request failed {0}", CacheKey);
1407 }
1408  
1409 // and cache the response
1410 lock (m_memoryCache)
1411 {
1412 m_memoryCache.AddOrUpdate(CacheKey, response, TimeSpan.FromSeconds(m_cacheTimeout));
1413 m_pendingRequests.Remove(CacheKey);
1414 }
1415  
1416 return response;
1417 }
1418  
1419 Thread.Sleep(50); // waiting for a web request to complete, 50msecs is reasonable
1420 }
1421  
1422 // if (!m_memoryCache.TryGetValue(CacheKey, out response))
1423 // {
1424 // m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: query not in the cache");
1425 // Util.PrintCallStack();
1426  
1427 // // if it wasn't in the cache, pass the request to the Simian Grid Services
1428 // response = WebUtil.PostToService(m_groupsServerURI, requestArgs);
1429  
1430 // // and cache the response
1431 // m_memoryCache.AddOrUpdate(CacheKey, response, TimeSpan.FromSeconds(m_cacheTimeout));
1432 // }
1433  
1434 // // return cached response
1435 // return response;
1436 }
1437 #endregion
1438  
1439 }
1440  
1441 }
1442