aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/ApplicationPlugins/Rest/RestPlugin.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/ApplicationPlugins/Rest/RestPlugin.cs417
1 files changed, 0 insertions, 417 deletions
diff --git a/OpenSim/ApplicationPlugins/Rest/RestPlugin.cs b/OpenSim/ApplicationPlugins/Rest/RestPlugin.cs
deleted file mode 100644
index a2425b5..0000000
--- a/OpenSim/ApplicationPlugins/Rest/RestPlugin.cs
+++ /dev/null
@@ -1,417 +0,0 @@
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.Collections.Generic;
30using System.IO;
31using System.Reflection;
32using System.Xml;
33using log4net;
34using Nini.Config;
35using OpenMetaverse;
36using OpenSim.Framework;
37using OpenSim.Framework.Servers;
38using OpenSim.Framework.Servers.HttpServer;
39
40namespace OpenSim.ApplicationPlugins.Rest
41{
42 public abstract class RestPlugin : IApplicationPlugin
43 {
44 #region properties
45
46 protected static readonly ILog m_log =
47 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48
49 private IConfig _config; // Configuration source: Rest Plugins
50 private IConfig _pluginConfig; // Configuration source: Plugin specific
51 private OpenSimBase _app; // The 'server'
52 private BaseHttpServer _httpd; // The server's RPC interface
53 private string _prefix; // URL prefix below
54 // which all REST URLs
55 // are living
56 // private StringWriter _sw = null;
57 // private RestXmlWriter _xw = null;
58
59 private string _godkey;
60 private int _reqk;
61
62 [ThreadStatic]
63 private static string _threadRequestID = String.Empty;
64
65 /// <summary>
66 /// Return an ever increasing request ID for logging
67 /// </summary>
68 protected string RequestID
69 {
70 get { return _reqk++.ToString(); }
71 set { _reqk = Convert.ToInt32(value); }
72 }
73
74 /// <summary>
75 /// Thread-constant message IDs for logging.
76 /// </summary>
77 protected string MsgID
78 {
79 get { return String.Format("[REST-{0}] #{1}", Name, _threadRequestID); }
80 set { _threadRequestID = value; }
81 }
82
83 /// <summary>
84 /// Returns true if Rest Plugins are enabled.
85 /// </summary>
86 public bool PluginsAreEnabled
87 {
88 get { return null != _config; }
89 }
90
91 /// <summary>
92 /// Returns true if specific Rest Plugin is enabled.
93 /// </summary>
94 public bool IsEnabled
95 {
96 get
97 {
98 return (null != _pluginConfig) && _pluginConfig.GetBoolean("enabled", false);
99 }
100 }
101
102 /// <summary>
103 /// OpenSimMain application
104 /// </summary>
105 public OpenSimBase App
106 {
107 get { return _app; }
108 }
109
110 /// <summary>
111 /// RPC server
112 /// </summary>
113 public BaseHttpServer HttpServer
114 {
115 get { return _httpd; }
116 }
117
118 /// <summary>
119 /// URL prefix to use for all REST handlers
120 /// </summary>
121 public string Prefix
122 {
123 get { return _prefix; }
124 }
125
126 /// <summary>
127 /// Access to GOD password string
128 /// </summary>
129 protected string GodKey
130 {
131 get { return _godkey; }
132 }
133
134 /// <summary>
135 /// Configuration of the plugin
136 /// </summary>
137 public IConfig Config
138 {
139 get { return _pluginConfig; }
140 }
141
142 /// <summary>
143 /// Name of the plugin
144 /// </summary>
145 public abstract string Name { get; }
146
147 /// <summary>
148 /// Return the config section name
149 /// </summary>
150 public abstract string ConfigName { get; }
151
152 // public XmlTextWriter XmlWriter
153 // {
154 // get
155 // {
156 // if (null == _xw)
157 // {
158 // _sw = new StringWriter();
159 // _xw = new RestXmlWriter(_sw);
160 // _xw.Formatting = Formatting.Indented;
161 // }
162 // return _xw;
163 // }
164 // }
165
166 // public string XmlWriterResult
167 // {
168 // get
169 // {
170 // _xw.Flush();
171 // _xw.Close();
172 // _xw = null;
173
174 // return _sw.ToString();
175 // }
176 // }
177
178 #endregion properties
179
180 #region methods
181
182 // TODO: required by IPlugin, but likely not at all right
183 private string m_version = "0.0";
184
185 public string Version
186 {
187 get { return m_version; }
188 }
189
190 public void Initialise()
191 {
192 m_log.Info("[RESTPLUGIN]: " + Name + " cannot be default-initialized!");
193 throw new PluginNotInitialisedException(Name);
194 }
195
196 /// <summary>
197 /// This method is called by OpenSimMain immediately after loading the
198 /// plugin and after basic server setup, but before running any server commands.
199 /// </summary>
200 /// <remarks>
201 /// Note that entries MUST be added to the active configuration files before
202 /// the plugin can be enabled.
203 /// </remarks>
204 public virtual void Initialise(OpenSimBase openSim)
205 {
206 RequestID = "0";
207 MsgID = RequestID;
208
209 try
210 {
211 if ((_config = openSim.ConfigSource.Source.Configs["RestPlugins"]) == null)
212 {
213 m_log.WarnFormat("{0} Rest Plugins not configured", MsgID);
214 return;
215 }
216
217 if (!_config.GetBoolean("enabled", false))
218 {
219 //m_log.WarnFormat("{0} Rest Plugins are disabled", MsgID);
220 return;
221 }
222
223 _app = openSim;
224 _httpd = openSim.HttpServer;
225
226 // Retrieve GOD key value, if any.
227 _godkey = _config.GetString("god_key", String.Empty);
228
229 // Retrive prefix if any.
230 _prefix = _config.GetString("prefix", "/admin");
231
232 // Get plugin specific config
233 _pluginConfig = openSim.ConfigSource.Source.Configs[ConfigName];
234
235 m_log.InfoFormat("{0} Rest Plugins Enabled", MsgID);
236 }
237 catch (Exception e)
238 {
239 // we can safely ignore this, as it just means that
240 // the key lookup in Configs failed, which signals to
241 // us that noone is interested in our services...they
242 // don't know what they are missing out on...
243 // NOTE: Under the present OpenSimulator implementation it is
244 // not possible for the openSimulator pointer to be null. However
245 // were the implementation to be changed, this could
246 // result in a silent initialization failure. Harmless
247 // except for lack of function and lack of any
248 // diagnostic indication as to why. The same is true if
249 // the HTTP server reference is bad.
250 // We should at least issue a message...
251 m_log.WarnFormat("{0} Initialization failed: {1}", MsgID, e.Message);
252 m_log.DebugFormat("{0} Initialization failed: {1}", MsgID, e.ToString());
253 }
254 }
255
256 public virtual void PostInitialise()
257 {
258 }
259
260 private List<RestStreamHandler> _handlers = new List<RestStreamHandler>();
261 private Dictionary<string, IHttpAgentHandler> _agents = new Dictionary<string, IHttpAgentHandler>();
262
263 /// <summary>
264 /// Add a REST stream handler to the underlying HTTP server.
265 /// </summary>
266 /// <param name="httpMethod">GET/PUT/POST/DELETE or
267 /// similar</param>
268 /// <param name="path">URL prefix</param>
269 /// <param name="method">RestMethod handler doing the actual work</param>
270 public virtual void AddRestStreamHandler(string httpMethod, string path, RestMethod method)
271 {
272 if (!IsEnabled) return;
273
274 if (!path.StartsWith(_prefix))
275 {
276 path = String.Format("{0}{1}", _prefix, path);
277 }
278
279 RestStreamHandler h = new RestStreamHandler(httpMethod, path, method);
280 _httpd.AddStreamHandler(h);
281 _handlers.Add(h);
282
283 m_log.DebugFormat("{0} Added REST handler {1} {2}", MsgID, httpMethod, path);
284 }
285
286 /// <summary>
287 /// Add a powerful Agent handler to the underlying HTTP
288 /// server.
289 /// </summary>
290 /// <param name="agentName">name of agent handler</param>
291 /// <param name="handler">agent handler method</param>
292 /// <returns>false when the plugin is disabled or the agent
293 /// handler could not be added. Any generated exceptions are
294 /// allowed to drop through to the caller, i.e. ArgumentException.
295 /// </returns>
296 public bool AddAgentHandler(string agentName, IHttpAgentHandler handler)
297 {
298 if (!IsEnabled) return false;
299 _agents.Add(agentName, handler);
300// return _httpd.AddAgentHandler(agentName, handler);
301
302 return false;
303 }
304
305 /// <summary>
306 /// Remove a powerful Agent handler from the underlying HTTP
307 /// server.
308 /// </summary>
309 /// <param name="agentName">name of agent handler</param>
310 /// <param name="handler">agent handler method</param>
311 /// <returns>false when the plugin is disabled or the agent
312 /// handler could not be removed. Any generated exceptions are
313 /// allowed to drop through to the caller, i.e. KeyNotFound.
314 /// </returns>
315 public bool RemoveAgentHandler(string agentName, IHttpAgentHandler handler)
316 {
317 if (!IsEnabled) return false;
318 if (_agents[agentName] == handler)
319 {
320 _agents.Remove(agentName);
321// return _httpd.RemoveAgentHandler(agentName, handler);
322 }
323 return false;
324 }
325
326 /// <summary>
327 /// Check whether the HTTP request came from god; that is, is
328 /// the god_key as configured in the config section supplied
329 /// via X-OpenSim-Godkey?
330 /// </summary>
331 /// <param name="request">HTTP request header</param>
332 /// <returns>true when the HTTP request came from god.</returns>
333 protected bool IsGod(IOSHttpRequest request)
334 {
335 string[] keys = request.Headers.GetValues("X-OpenSim-Godkey");
336 if (null == keys) return false;
337
338 // we take the last key supplied
339 return keys[keys.Length - 1] == _godkey;
340 }
341
342 /// <summary>
343 /// Checks wether the X-OpenSim-Password value provided in the
344 /// HTTP header is indeed the password on file for the avatar
345 /// specified by the UUID
346 /// </summary>
347 protected bool IsVerifiedUser(IOSHttpRequest request, UUID uuid)
348 {
349 // XXX under construction
350 return false;
351 }
352
353 /// <summary>
354 /// Clean up and remove all handlers that were added earlier.
355 /// </summary>
356 public virtual void Close()
357 {
358 foreach (RestStreamHandler h in _handlers)
359 {
360 _httpd.RemoveStreamHandler(h.HttpMethod, h.Path);
361 }
362 _handlers = null;
363// foreach (KeyValuePair<string, IHttpAgentHandler> h in _agents)
364// {
365// _httpd.RemoveAgentHandler(h.Key, h.Value);
366// }
367 _agents = null;
368 }
369
370 public virtual void Dispose()
371 {
372 Close();
373 }
374
375 /// <summary>
376 /// Return a failure message.
377 /// </summary>
378 /// <param name="method">origin of the failure message</param>
379 /// <param name="message">failure message</param>
380 /// <remarks>This should probably set a return code as
381 /// well. (?)</remarks>
382 protected string Failure(IOSHttpResponse response, OSHttpStatusCode status,
383 string method, string format, params string[] msg)
384 {
385 string m = String.Format(format, msg);
386
387 response.StatusCode = (int) status;
388 response.StatusDescription = m;
389
390 m_log.ErrorFormat("{0} {1} failed: {2}", MsgID, method, m);
391 return String.Format("<error>{0}</error>", m);
392 }
393
394 /// <summary>
395 /// Return a failure message.
396 /// </summary>
397 /// <param name="method">origin of the failure message</param>
398 /// <param name="e">exception causing the failure message</param>
399 /// <remarks>This should probably set a return code as
400 /// well. (?)</remarks>
401 public string Failure(IOSHttpResponse response, OSHttpStatusCode status,
402 string method, Exception e)
403 {
404 string m = String.Format("exception occurred: {0}", e.Message);
405
406 response.StatusCode = (int) status;
407 response.StatusDescription = m;
408
409 m_log.DebugFormat("{0} {1} failed: {2}", MsgID, method, e.ToString());
410 m_log.ErrorFormat("{0} {1} failed: {2}", MsgID, method, e.Message);
411
412 return String.Format("<error>{0}</error>", e.Message);
413 }
414
415 #endregion methods
416 }
417}