From 4e93228e25a941dde4b01c4ec934cd1907096a6f Mon Sep 17 00:00:00 2001
From: Dr Scofield
Date: Mon, 19 May 2008 11:52:51 +0000
Subject: fixing exception when RestPlugin not configured. refactors
RestRegionPlugin, adds error checking.
---
.../Rest/Regions/GETRestRegionPlugin.cs | 184 +++++++++++++++++++++
.../Rest/Regions/RegionDetails.cs | 34 +++-
.../Rest/Regions/RestRegionPlugin.cs | 76 ++-------
OpenSim/ApplicationPlugins/Rest/RestPlugin.cs | 74 +++++++--
4 files changed, 288 insertions(+), 80 deletions(-)
create mode 100644 OpenSim/ApplicationPlugins/Rest/Regions/GETRestRegionPlugin.cs
diff --git a/OpenSim/ApplicationPlugins/Rest/Regions/GETRestRegionPlugin.cs b/OpenSim/ApplicationPlugins/Rest/Regions/GETRestRegionPlugin.cs
new file mode 100644
index 0000000..2b006e0
--- /dev/null
+++ b/OpenSim/ApplicationPlugins/Rest/Regions/GETRestRegionPlugin.cs
@@ -0,0 +1,184 @@
+/*
+* Copyright (c) Contributors, http://opensimulator.org/
+* See CONTRIBUTORS.TXT for a full list of copyright holders.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of the OpenSim Project nor the
+* names of its contributors may be used to endorse or promote products
+* derived from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*/
+
+using System;
+using System.Threading;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Net;
+using System.Reflection;
+using System.Text.RegularExpressions;
+using System.Timers;
+using System.Xml;
+using System.Xml.Serialization;
+using libsecondlife;
+using Mono.Addins;
+using Nwc.XmlRpc;
+using Nini.Config;
+using OpenSim.Framework;
+using OpenSim.Framework.Console;
+using OpenSim.Framework.Servers;
+using OpenSim.Framework.Communications;
+using OpenSim.Region.Environment.Scenes;
+using OpenSim.ApplicationPlugins.Rest;
+
+namespace OpenSim.ApplicationPlugins.Rest.Regions
+{
+
+ public partial class RestRegionPlugin : RestPlugin
+ {
+ #region GET methods
+ public string GetHandler(string request, string path, string param)
+ {
+ m_log.DebugFormat("{0} GET path {1} param {2}", MsgID, path, param);
+
+ try
+ {
+ // param empty: regions list
+ if (String.IsNullOrEmpty(param)) return GetHandlerRegions();
+
+ // param not empty: specific region
+ return GetHandlerRegion(param);
+ }
+ catch (Exception e)
+ {
+ return Failure("GET", e);
+ }
+ }
+
+ public string GetHandlerRegions()
+ {
+ XmlWriter.WriteStartElement(String.Empty, "regions", String.Empty);
+ foreach (Scene s in App.SceneManager.Scenes)
+ {
+ XmlWriter.WriteStartElement(String.Empty, "uuid", String.Empty);
+ XmlWriter.WriteString(s.RegionInfo.RegionID.ToString());
+ XmlWriter.WriteEndElement();
+ }
+ XmlWriter.WriteEndElement();
+
+ return XmlWriterResult;
+ }
+
+ protected string ShortRegionInfo(string key, string value)
+ {
+ if (String.IsNullOrEmpty(value) ||
+ String.IsNullOrEmpty(key)) return null;
+
+ XmlWriter.WriteStartElement(String.Empty, "region", String.Empty);
+ XmlWriter.WriteStartElement(String.Empty, key, String.Empty);
+ XmlWriter.WriteString(value);
+ XmlWriter.WriteEndDocument();
+
+ return XmlWriterResult;
+ }
+
+ public string GetHandlerRegion(string param)
+ {
+ // be resilient and don't get confused by a terminating '/'
+ param = param.TrimEnd(new char[]{'/'});
+ string[] comps = param.Split('/');
+ LLUUID regionID = (LLUUID)comps[0];
+
+ m_log.DebugFormat("{0} GET region UUID {1}", MsgID, regionID.ToString());
+
+ if (LLUUID.Zero == regionID) throw new Exception("missing region ID");
+
+ Scene scene = null;
+ App.SceneManager.TryGetScene(regionID, out scene);
+ if (null == scene) return Failure("GET", "cannot find region");
+
+ RegionDetails details = new RegionDetails(scene.RegionInfo);
+
+ // m_log.DebugFormat("{0} GET comps {1}", MsgID, comps.Length);
+ // for (int i = 0; i < comps.Length; i++) m_log.DebugFormat("{0} GET comps[{1}] >{2}<", MsgID, i, comps[i]);
+
+ if (1 == comps.Length)
+ {
+ // complete region details requested
+ XmlSerializer xs = new XmlSerializer(typeof(RegionDetails));
+ xs.Serialize(XmlWriter, details);
+ return XmlWriterResult;
+ }
+
+ if (2 == comps.Length) {
+ string resp = ShortRegionInfo(comps[1], details[comps[1]]);
+ if (null != resp) return resp;
+
+ // m_log.DebugFormat("{0} GET comps advanced: >{1}<", MsgID, comps[1]);
+
+ // check for {terrain,stats,prims}
+ switch (comps[1].ToLower())
+ {
+ case "terrain":
+ return RegionTerrain(scene);
+
+ case "stats":
+ return RegionStats(scene);
+
+ case "prims":
+ return RegionPrims(scene);
+ }
+ }
+ return Failure("GET", "too many parameters");
+ }
+ #endregion GET methods
+
+ protected string RegionTerrain(Scene scene)
+ {
+ return Failure("GET", "terrain not implemented");
+ }
+
+ protected string RegionStats(Scene scene)
+ {
+ int users = scene.GetAvatars().Count;
+ int objects = scene.Entities.Count - users;
+
+ XmlWriter.WriteStartElement(String.Empty, "region", String.Empty);
+ XmlWriter.WriteStartElement(String.Empty, "stats", String.Empty);
+
+ XmlWriter.WriteStartElement(String.Empty, "users", String.Empty);
+ XmlWriter.WriteString(users.ToString());
+ XmlWriter.WriteEndElement();
+
+ XmlWriter.WriteStartElement(String.Empty, "objects", String.Empty);
+ XmlWriter.WriteString(objects.ToString());
+ XmlWriter.WriteEndElement();
+
+ XmlWriter.WriteEndDocument();
+
+ return XmlWriterResult;
+ }
+
+ protected string RegionPrims(Scene scene)
+ {
+ return Failure("GET", "prims not implemented");
+ }
+ }
+}
diff --git a/OpenSim/ApplicationPlugins/Rest/Regions/RegionDetails.cs b/OpenSim/ApplicationPlugins/Rest/Regions/RegionDetails.cs
index 5102e3f..c86c67f 100644
--- a/OpenSim/ApplicationPlugins/Rest/Regions/RegionDetails.cs
+++ b/OpenSim/ApplicationPlugins/Rest/Regions/RegionDetails.cs
@@ -23,7 +23,7 @@
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*
+*
*/
using libsecondlife;
@@ -65,8 +65,38 @@ namespace OpenSim.ApplicationPlugins.Rest.Regions
region_external_hostname = regInfo.ExternalHostName;
if (!String.IsNullOrEmpty(regInfo.MasterAvatarFirstName))
- region_owner = String.Format("{0} {1}", regInfo.MasterAvatarFirstName,
+ region_owner = String.Format("{0} {1}", regInfo.MasterAvatarFirstName,
regInfo.MasterAvatarLastName);
}
+
+ public string this[string idx]
+ {
+ get
+ {
+ switch(idx.ToLower())
+ {
+ case "name":
+ return region_name;
+ case "id":
+ return region_id;
+ case "location":
+ return String.Format("{0}{1}", region_x, region_y);
+ case "owner":
+ return region_owner;
+ case "owner_id":
+ return region_owner_id;
+ case "http_port":
+ return region_http_port.ToString();
+ case "server_uri":
+ return region_server_uri;
+ case "external_hostname":
+ case "hostname":
+ return region_external_hostname;
+
+ default:
+ return null;
+ }
+ }
+ }
}
}
\ No newline at end of file
diff --git a/OpenSim/ApplicationPlugins/Rest/Regions/RestRegionPlugin.cs b/OpenSim/ApplicationPlugins/Rest/Regions/RestRegionPlugin.cs
index 0716cf6..9b888fa 100644
--- a/OpenSim/ApplicationPlugins/Rest/Regions/RestRegionPlugin.cs
+++ b/OpenSim/ApplicationPlugins/Rest/Regions/RestRegionPlugin.cs
@@ -23,7 +23,7 @@
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*
+*
*/
using System;
@@ -55,14 +55,11 @@ namespace OpenSim.ApplicationPlugins.Rest.Regions
{
[Extension("/OpenSim/Startup")]
- public class RestRegionPlugin : RestPlugin
+ public partial class RestRegionPlugin : RestPlugin
{
- private static readonly log4net.ILog _log =
- log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
-
#region overriding properties
- public override string Name
- {
+ public override string Name
+ {
get { return "REGION"; }
}
@@ -86,18 +83,20 @@ namespace OpenSim.ApplicationPlugins.Rest.Regions
try
{
base.Initialise(openSim);
- if (IsEnabled)
- m_log.InfoFormat("{0} Rest Plugins Enabled", MsgID);
- else
+ if (!IsEnabled)
+ {
m_log.WarnFormat("{0} Rest Plugins are disabled", MsgID);
+ return;
+ }
+ m_log.InfoFormat("{0} REST region plugin enabled", MsgID);
// add REST method handlers
AddRestStreamHandler("GET", "/regions/", GetHandler);
}
catch (Exception e)
{
- _log.WarnFormat("{0} Initialization failed: {1}", MsgID, e.Message);
- _log.DebugFormat("{0} Initialization failed: {1}", MsgID, e.ToString());
+ m_log.WarnFormat("{0} Initialization failed: {1}", MsgID, e.Message);
+ m_log.DebugFormat("{0} Initialization failed: {1}", MsgID, e.ToString());
}
}
@@ -105,58 +104,5 @@ namespace OpenSim.ApplicationPlugins.Rest.Regions
{
}
#endregion overriding methods
-
- #region methods
- public string GetHandler(string request, string path, string param)
- {
- m_log.DebugFormat("{0} GET path {1} param {2}", MsgID, path, param);
-
- // param empty: regions list
- if (String.IsNullOrEmpty(param)) return GetHandlerRegions();
-
- return GetHandlerRegion(param);
- }
-
- public string GetHandlerRegions()
- {
- StringWriter sw = new StringWriter();
- XmlTextWriter xw = new XmlTextWriter(sw);
- xw.Formatting = Formatting.Indented;
-
- xw.WriteStartElement(String.Empty, "regions", String.Empty);
- foreach (Scene s in App.SceneManager.Scenes)
- {
- xw.WriteStartElement(String.Empty, "uuid", String.Empty);
- xw.WriteString(s.RegionInfo.RegionID.ToString());
- xw.WriteEndElement();
- }
- xw.WriteEndElement();
- xw.Close();
-
- return sw.ToString();
- }
-
- public string GetHandlerRegion(string param)
- {
- string[] comps = param.Split('/');
- LLUUID regionID = (LLUUID)comps[0];
- _log.DebugFormat("{0} region UUID {1}", MsgID, regionID.ToString());
-
- if (LLUUID.Zero == regionID) throw new Exception("missing region ID");
-
- Scene scene = null;
- App.SceneManager.TryGetScene(regionID, out scene);
-
- XmlSerializer xs = new XmlSerializer(typeof(RegionDetails));
- StringWriter sw = new StringWriter();
- XmlTextWriter xw = new XmlTextWriter(sw);
- xw.Formatting = Formatting.Indented;
-
- xs.Serialize(xw, new RegionDetails(scene.RegionInfo));
- xw.Close();
-
- return sw.ToString();
- }
- #endregion methods
}
}
diff --git a/OpenSim/ApplicationPlugins/Rest/RestPlugin.cs b/OpenSim/ApplicationPlugins/Rest/RestPlugin.cs
index 05ea956..199bff8 100644
--- a/OpenSim/ApplicationPlugins/Rest/RestPlugin.cs
+++ b/OpenSim/ApplicationPlugins/Rest/RestPlugin.cs
@@ -23,16 +23,18 @@
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*
+*
*/
using System;
using System.Threading;
using System.Collections;
using System.Collections.Generic;
+using System.IO;
using System.Net;
using System.Reflection;
using System.Timers;
+using System.Xml;
using libsecondlife;
using Mono.Addins;
using Nwc.XmlRpc;
@@ -54,14 +56,18 @@ namespace OpenSim.ApplicationPlugins.Rest
{
#region properties
- protected static readonly log4net.ILog m_log =
+ protected static readonly log4net.ILog m_log =
log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private IConfig _config; // Configuration source: Rest Plugins
private IConfig _pluginConfig; // Configuration source: Plugin specific
private OpenSimMain _app; // The 'server'
private BaseHttpServer _httpd; // The server's RPC interface
- private string _prefix; // URL prefix below which all REST URLs are living
+ private string _prefix; // URL prefix below
+ // which all REST URLs
+ // are living
+ private StringWriter _sw = null;
+ private XmlTextWriter _xw = null;
private string _godkey;
private int _reqk;
@@ -100,8 +106,8 @@ namespace OpenSim.ApplicationPlugins.Rest
///
public bool IsEnabled
{
- get
- {
+ get
+ {
return (null != _pluginConfig) && _pluginConfig.GetBoolean("enabled", false);
}
}
@@ -109,7 +115,7 @@ namespace OpenSim.ApplicationPlugins.Rest
///
/// OpenSimMain application
///
- public OpenSimMain App
+ public OpenSimMain App
{
get { return _app; }
}
@@ -117,7 +123,7 @@ namespace OpenSim.ApplicationPlugins.Rest
///
/// RPC server
///
- public BaseHttpServer HttpServer
+ public BaseHttpServer HttpServer
{
get { return _httpd; }
}
@@ -147,6 +153,29 @@ namespace OpenSim.ApplicationPlugins.Rest
/// Return the config section name
///
public abstract string ConfigName { get; }
+
+ public XmlTextWriter XmlWriter
+ {
+ get {
+ if (null == _xw)
+ {
+ _sw = new StringWriter();
+ _xw = new XmlTextWriter(_sw);
+ _xw.Formatting = Formatting.Indented;
+ }
+ return _xw; }
+ }
+
+ public string XmlWriterResult
+ {
+ get
+ {
+ _xw.Flush();
+ _xw = null;
+
+ return _sw.ToString();
+ }
+ }
#endregion properties
@@ -171,7 +200,7 @@ namespace OpenSim.ApplicationPlugins.Rest
return;
}
- if (!_config.GetBoolean("enabled", false))
+ if (!_config.GetBoolean("enabled", false))
{
m_log.WarnFormat("{0} Rest Plugins are disabled", MsgID);
return;
@@ -184,10 +213,11 @@ namespace OpenSim.ApplicationPlugins.Rest
_godkey = _config.GetString("god_key", String.Empty);
// Retrive prefix if any.
_prefix = _config.GetString("prefix", "/admin");
-
+
// Get plugin specific config
_pluginConfig = openSim.ConfigSource.Configs[ConfigName];
+
m_log.InfoFormat("{0} Rest Plugins Enabled", MsgID);
}
catch (Exception e)
@@ -200,7 +230,7 @@ namespace OpenSim.ApplicationPlugins.Rest
// not possible for the openSim pointer to be null. However
// were the implementation to be changed, this could
// result in a silent initialization failure. Harmless
- // except for lack of function and lack of any
+ // except for lack of function and lack of any
// diagnostic indication as to why. The same is true if
// the HTTP server reference is bad.
// We should at least issue a message...
@@ -214,7 +244,9 @@ namespace OpenSim.ApplicationPlugins.Rest
public void AddRestStreamHandler(string httpMethod, string path, RestMethod method)
{
- if (!path.StartsWith(_prefix))
+ if (!IsEnabled) return;
+
+ if (!path.StartsWith(_prefix))
{
path = String.Format("{0}{1}", _prefix, path);
}
@@ -226,10 +258,12 @@ namespace OpenSim.ApplicationPlugins.Rest
m_log.DebugFormat("{0} Added REST handler {1} {2}", MsgID, httpMethod, path);
}
-
- public bool VerifyGod(string key)
+
+ protected bool VerifyGod(string key)
{
if (String.IsNullOrEmpty(key)) return false;
+ if (!IsEnabled) return false;
+
return key == _godkey;
}
@@ -241,6 +275,20 @@ namespace OpenSim.ApplicationPlugins.Rest
}
_handlers = null;
}
+
+ protected string Failure(string method, string message)
+ {
+ m_log.ErrorFormat("{0} {1} failed: {2}", MsgID, method, message);
+ return String.Format("{0}", message);
+ }
+
+ public string Failure(string method, Exception e)
+ {
+ m_log.DebugFormat("{0} {1} failed: {2}", MsgID, method, e.ToString());
+ m_log.ErrorFormat("{0} {1} failed: {2}", MsgID, method, e.Message);
+
+ return String.Format("{0}", e.Message);
+ }
#endregion methods
}
}
--
cgit v1.1