parent
7025a8040e
commit
50bc51b642
|
@ -0,0 +1,236 @@
|
|||
/*
|
||||
* 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 libsecondlife;
|
||||
using Nini.Config;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Servers;
|
||||
using OpenSim.Framework.Communications;
|
||||
using OpenSim.Framework.Communications.Cache;
|
||||
|
||||
namespace OpenSim.ApplicationPlugins.Rest.Inventory
|
||||
{
|
||||
|
||||
public class RestTestServices : IRest
|
||||
{
|
||||
|
||||
private bool enabled = false;
|
||||
private string qPrefix = "test";
|
||||
|
||||
// A simple constructor is used to handle any once-only
|
||||
// initialization of working classes.
|
||||
|
||||
public RestTestServices()
|
||||
{
|
||||
|
||||
Rest.Log.InfoFormat("{0} Test services initializing", MsgId);
|
||||
Rest.Log.InfoFormat("{0} Using REST Implementation Version {1}", MsgId, Rest.Version);
|
||||
|
||||
// If a relative path was specified, make it absolute by adding
|
||||
// the standard prefix, e.g. /admin
|
||||
|
||||
if (!qPrefix.StartsWith(Rest.UrlPathSeparator))
|
||||
{
|
||||
qPrefix = Rest.Prefix + Rest.UrlPathSeparator + qPrefix;
|
||||
}
|
||||
|
||||
// Load test cases
|
||||
|
||||
loadTests();
|
||||
foreach ( ITest test in tests )
|
||||
{
|
||||
test.Initialize();
|
||||
}
|
||||
|
||||
// Register interface
|
||||
|
||||
Rest.Plugin.AddPathHandler(DoTests,qPrefix,Allocate);
|
||||
|
||||
// Activate
|
||||
|
||||
enabled = true;
|
||||
|
||||
Rest.Log.InfoFormat("{0} Test services initialization complete", MsgId);
|
||||
|
||||
}
|
||||
|
||||
// Post-construction, pre-enabled initialization opportunity
|
||||
// Not currently exploited.
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
}
|
||||
|
||||
// Called by the plug-in to halt REST processing. Local processing is
|
||||
// disabled, and control blocks until all current processing has
|
||||
// completed. No new processing will be started
|
||||
|
||||
public void Close()
|
||||
{
|
||||
enabled = false;
|
||||
foreach ( ITest test in tests )
|
||||
{
|
||||
test.Close();
|
||||
}
|
||||
Rest.Log.InfoFormat("{0} Test services closing down", MsgId);
|
||||
}
|
||||
|
||||
// Properties
|
||||
|
||||
internal string MsgId
|
||||
{
|
||||
get { return Rest.MsgId; }
|
||||
}
|
||||
|
||||
#region Interface
|
||||
|
||||
private RequestData Allocate(OSHttpRequest request, OSHttpResponse response)
|
||||
{
|
||||
return new RequestData(request, response, qPrefix);
|
||||
}
|
||||
|
||||
// Inventory Handler
|
||||
|
||||
private void DoTests(RequestData rdata)
|
||||
{
|
||||
|
||||
if (!enabled) return;
|
||||
|
||||
// Now that we know this is a serious attempt to
|
||||
// access inventory data, we should find out who
|
||||
// is asking, and make sure they are authorized
|
||||
// to do so. We need to validate the caller's
|
||||
// identity before revealing anything about the
|
||||
// status quo. Authenticate throws an exception
|
||||
// via Fail if no identity information is present.
|
||||
//
|
||||
// With the present HTTP server we can't use the
|
||||
// builtin authentication mechanisms because they
|
||||
// would be enforced for all in-bound requests.
|
||||
// Instead we look at the headers ourselves and
|
||||
// handle authentication directly.
|
||||
|
||||
try
|
||||
{
|
||||
if (!rdata.IsAuthenticated)
|
||||
{
|
||||
rdata.Fail(Rest.HttpStatusCodeNotAuthorized, Rest.HttpStatusDescNotAuthorized);
|
||||
}
|
||||
}
|
||||
catch (RestException e)
|
||||
{
|
||||
if (e.statusCode == Rest.HttpStatusCodeNotAuthorized)
|
||||
{
|
||||
Rest.Log.WarnFormat("{0} User not authenticated", MsgId);
|
||||
Rest.Log.DebugFormat("{0} Authorization header: {1}", MsgId, rdata.request.Headers.Get("Authorization"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Rest.Log.ErrorFormat("{0} User authentication failed", MsgId);
|
||||
Rest.Log.DebugFormat("{0} Authorization header: {1}", MsgId, rdata.request.Headers.Get("Authorization"));
|
||||
}
|
||||
throw (e);
|
||||
}
|
||||
|
||||
// Check that a test was specified
|
||||
|
||||
if (rdata.parameters.Length < 1)
|
||||
{
|
||||
Rest.Log.DebugFormat("{0} Insufficient parameters", MsgId);
|
||||
rdata.Fail(Rest.HttpStatusCodeBadRequest, Rest.HttpStatusDescBadRequest);
|
||||
}
|
||||
|
||||
// Select the test
|
||||
|
||||
foreach (ITest test in tests)
|
||||
{
|
||||
if (!rdata.handled)
|
||||
test.Execute(rdata);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endregion Interface
|
||||
|
||||
private static bool testsLoaded = false;
|
||||
private static List<Type> classes = new List<Type>();
|
||||
private static List<ITest> tests = new List<ITest>();
|
||||
private static Type[] parms = new Type[1];
|
||||
private static Object[] args = new Object[1];
|
||||
|
||||
static RestTestServices()
|
||||
{
|
||||
Module[] mods = Assembly.GetExecutingAssembly().GetModules();
|
||||
foreach (Module m in mods)
|
||||
{
|
||||
Type[] types = m.GetTypes();
|
||||
foreach (Type t in types)
|
||||
{
|
||||
if (t.GetInterface("ITest") != null)
|
||||
{
|
||||
classes.Add(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This routine loads all of the handlers discovered during
|
||||
/// instance initialization. Each handler is responsible for
|
||||
/// registering itself with this handler.
|
||||
/// I was not able to make this code work in a constructor.
|
||||
/// </summary>
|
||||
private void loadTests()
|
||||
{
|
||||
lock(tests)
|
||||
{
|
||||
if (!testsLoaded)
|
||||
{
|
||||
parms[0] = this.GetType();
|
||||
args[0] = this;
|
||||
|
||||
ConstructorInfo ci;
|
||||
Object ht;
|
||||
|
||||
foreach (Type t in classes)
|
||||
{
|
||||
ci = t.GetConstructor(parms);
|
||||
ht = ci.Invoke(args);
|
||||
tests.Add((ITest)ht);
|
||||
}
|
||||
testsLoaded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
namespace OpenSim.ApplicationPlugins.Rest.Inventory
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// This interface represents the boundary between the general purpose
|
||||
/// REST plugin handling, and the functionally specific handlers. The
|
||||
/// handler knows only to initialzie and terminate all such handlers
|
||||
/// that it finds.
|
||||
/// </summary>
|
||||
|
||||
internal interface ITest
|
||||
{
|
||||
void Initialize();
|
||||
void Execute(RequestData rdata);
|
||||
void Close();
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue