aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs')
-rw-r--r--OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs367
1 files changed, 367 insertions, 0 deletions
diff --git a/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
new file mode 100644
index 0000000..98396ff
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
@@ -0,0 +1,367 @@
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
28using System;
29using System.Reflection;
30using System.Collections.Generic;
31using Nini.Config;
32using log4net;
33using OpenSim.Framework;
34using OpenSim.Region.Framework.Interfaces;
35using OpenSim.Region.Framework.Scenes;
36using Mono.Addins;
37using OpenMetaverse;
38using System.Linq;
39using System.Linq.Expressions;
40
41namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms
42{
43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ScriptModuleCommsModule")]
44 class ScriptModuleCommsModule : INonSharedRegionModule, IScriptModuleComms
45 {
46 private static readonly ILog m_log =
47 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48
49 private Dictionary<string,object> m_constants = new Dictionary<string,object>();
50
51#region ScriptInvocation
52 protected class ScriptInvocationData
53 {
54 public Delegate ScriptInvocationDelegate { get; private set; }
55 public string FunctionName { get; private set; }
56 public Type[] TypeSignature { get; private set; }
57 public Type ReturnType { get; private set; }
58
59 public ScriptInvocationData(string fname, Delegate fn, Type[] callsig, Type returnsig)
60 {
61 FunctionName = fname;
62 ScriptInvocationDelegate = fn;
63 TypeSignature = callsig;
64 ReturnType = returnsig;
65 }
66 }
67
68 private Dictionary<string,ScriptInvocationData> m_scriptInvocation = new Dictionary<string,ScriptInvocationData>();
69#endregion
70
71 private IScriptModule m_scriptModule = null;
72 public event ScriptCommand OnScriptCommand;
73
74#region RegionModuleInterface
75 public void Initialise(IConfigSource config)
76 {
77 }
78
79 public void AddRegion(Scene scene)
80 {
81 scene.RegisterModuleInterface<IScriptModuleComms>(this);
82 }
83
84 public void RemoveRegion(Scene scene)
85 {
86 }
87
88 public void RegionLoaded(Scene scene)
89 {
90 m_scriptModule = scene.RequestModuleInterface<IScriptModule>();
91
92 if (m_scriptModule != null)
93 m_log.Info("[MODULE COMMANDS]: Script engine found, module active");
94 }
95
96 public string Name
97 {
98 get { return "ScriptModuleCommsModule"; }
99 }
100
101 public Type ReplaceableInterface
102 {
103 get { return null; }
104 }
105
106 public void Close()
107 {
108 }
109#endregion
110
111#region ScriptModuleComms
112
113 public void RaiseEvent(UUID script, string id, string module, string command, string k)
114 {
115 ScriptCommand c = OnScriptCommand;
116
117 if (c == null)
118 return;
119
120 c(script, id, module, command, k);
121 }
122
123 public void DispatchReply(UUID script, int code, string text, string k)
124 {
125 if (m_scriptModule == null)
126 return;
127
128 Object[] args = new Object[] {-1, code, text, k};
129
130 m_scriptModule.PostScriptEvent(script, "link_message", args);
131 }
132
133 private static MethodInfo GetMethodInfoFromType(Type target, string meth, bool searchInstanceMethods)
134 {
135 BindingFlags getMethodFlags =
136 BindingFlags.NonPublic | BindingFlags.Public;
137
138 if (searchInstanceMethods)
139 getMethodFlags |= BindingFlags.Instance;
140 else
141 getMethodFlags |= BindingFlags.Static;
142
143 return target.GetMethod(meth, getMethodFlags);
144 }
145
146 public void RegisterScriptInvocation(object target, string meth)
147 {
148 MethodInfo mi = GetMethodInfoFromType(target.GetType(), meth, true);
149 if (mi == null)
150 {
151 m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}", meth);
152 return;
153 }
154
155 RegisterScriptInvocation(target, mi);
156 }
157
158 public void RegisterScriptInvocation(object target, string[] meth)
159 {
160 foreach (string m in meth)
161 RegisterScriptInvocation(target, m);
162 }
163
164 public void RegisterScriptInvocation(object target, MethodInfo mi)
165 {
166 m_log.DebugFormat("[MODULE COMMANDS] Register method {0} from type {1}", mi.Name, (target is Type) ? ((Type)target).Name : target.GetType().Name);
167
168 Type delegateType;
169 List<Type> typeArgs = mi.GetParameters()
170 .Select(p => p.ParameterType)
171 .ToList();
172
173 if (mi.ReturnType == typeof(void))
174 {
175 delegateType = Expression.GetActionType(typeArgs.ToArray());
176 }
177 else
178 {
179 typeArgs.Add(mi.ReturnType);
180 delegateType = Expression.GetFuncType(typeArgs.ToArray());
181 }
182
183 Delegate fcall;
184 if (!(target is Type))
185 fcall = Delegate.CreateDelegate(delegateType, target, mi);
186 else
187 fcall = Delegate.CreateDelegate(delegateType, (Type)target, mi.Name);
188
189 lock (m_scriptInvocation)
190 {
191 ParameterInfo[] parameters = fcall.Method.GetParameters();
192 if (parameters.Length < 2) // Must have two UUID params
193 return;
194
195 // Hide the first two parameters
196 Type[] parmTypes = new Type[parameters.Length - 2];
197 for (int i = 2; i < parameters.Length; i++)
198 parmTypes[i - 2] = parameters[i].ParameterType;
199 m_scriptInvocation[fcall.Method.Name] = new ScriptInvocationData(fcall.Method.Name, fcall, parmTypes, fcall.Method.ReturnType);
200 }
201 }
202
203 public void RegisterScriptInvocation(Type target, string[] methods)
204 {
205 foreach (string method in methods)
206 {
207 MethodInfo mi = GetMethodInfoFromType(target, method, false);
208 if (mi == null)
209 m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}", method);
210 else
211 RegisterScriptInvocation(target, mi);
212 }
213 }
214
215 public void RegisterScriptInvocations(IRegionModuleBase target)
216 {
217 foreach(MethodInfo method in target.GetType().GetMethods(
218 BindingFlags.Public | BindingFlags.Instance |
219 BindingFlags.Static))
220 {
221 if(method.GetCustomAttributes(
222 typeof(ScriptInvocationAttribute), true).Any())
223 {
224 if(method.IsStatic)
225 RegisterScriptInvocation(target.GetType(), method);
226 else
227 RegisterScriptInvocation(target, method);
228 }
229 }
230 }
231
232 public Delegate[] GetScriptInvocationList()
233 {
234 List<Delegate> ret = new List<Delegate>();
235
236 lock (m_scriptInvocation)
237 {
238 foreach (ScriptInvocationData d in m_scriptInvocation.Values)
239 ret.Add(d.ScriptInvocationDelegate);
240 }
241 return ret.ToArray();
242 }
243
244 public string LookupModInvocation(string fname)
245 {
246 lock (m_scriptInvocation)
247 {
248 ScriptInvocationData sid;
249 if (m_scriptInvocation.TryGetValue(fname,out sid))
250 {
251 if (sid.ReturnType == typeof(string))
252 return "modInvokeS";
253 else if (sid.ReturnType == typeof(int))
254 return "modInvokeI";
255 else if (sid.ReturnType == typeof(float))
256 return "modInvokeF";
257 else if (sid.ReturnType == typeof(UUID))
258 return "modInvokeK";
259 else if (sid.ReturnType == typeof(OpenMetaverse.Vector3))
260 return "modInvokeV";
261 else if (sid.ReturnType == typeof(OpenMetaverse.Quaternion))
262 return "modInvokeR";
263 else if (sid.ReturnType == typeof(object[]))
264 return "modInvokeL";
265
266 m_log.WarnFormat("[MODULE COMMANDS] failed to find match for {0} with return type {1}",fname,sid.ReturnType.Name);
267 }
268 }
269
270 return null;
271 }
272
273 public Delegate LookupScriptInvocation(string fname)
274 {
275 lock (m_scriptInvocation)
276 {
277 ScriptInvocationData sid;
278 if (m_scriptInvocation.TryGetValue(fname,out sid))
279 return sid.ScriptInvocationDelegate;
280 }
281
282 return null;
283 }
284
285 public Type[] LookupTypeSignature(string fname)
286 {
287 lock (m_scriptInvocation)
288 {
289 ScriptInvocationData sid;
290 if (m_scriptInvocation.TryGetValue(fname,out sid))
291 return sid.TypeSignature;
292 }
293
294 return null;
295 }
296
297 public Type LookupReturnType(string fname)
298 {
299 lock (m_scriptInvocation)
300 {
301 ScriptInvocationData sid;
302 if (m_scriptInvocation.TryGetValue(fname,out sid))
303 return sid.ReturnType;
304 }
305
306 return null;
307 }
308
309 public object InvokeOperation(UUID hostid, UUID scriptid, string fname, params object[] parms)
310 {
311 List<object> olist = new List<object>();
312 olist.Add(hostid);
313 olist.Add(scriptid);
314 foreach (object o in parms)
315 olist.Add(o);
316 Delegate fn = LookupScriptInvocation(fname);
317 return fn.DynamicInvoke(olist.ToArray());
318 }
319
320 /// <summary>
321 /// Operation to for a region module to register a constant to be used
322 /// by the script engine
323 /// </summary>
324 public void RegisterConstant(string cname, object value)
325 {
326 m_log.DebugFormat("[MODULE COMMANDS] register constant <{0}> with value {1}",cname,value.ToString());
327 lock (m_constants)
328 {
329 m_constants.Add(cname,value);
330 }
331 }
332
333 public void RegisterConstants(IRegionModuleBase target)
334 {
335 foreach (FieldInfo field in target.GetType().GetFields(
336 BindingFlags.Public | BindingFlags.Static |
337 BindingFlags.Instance))
338 {
339 if (field.GetCustomAttributes(
340 typeof(ScriptConstantAttribute), true).Any())
341 {
342 RegisterConstant(field.Name, field.GetValue(target));
343 }
344 }
345 }
346
347 /// <summary>
348 /// Operation to check for a registered constant
349 /// </summary>
350 public object LookupModConstant(string cname)
351 {
352 // m_log.DebugFormat("[MODULE COMMANDS] lookup constant <{0}>",cname);
353
354 lock (m_constants)
355 {
356 object value = null;
357 if (m_constants.TryGetValue(cname,out value))
358 return value;
359 }
360
361 return null;
362 }
363
364#endregion
365
366 }
367}