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