| #if TESTFRAMEWORK |
| // LUCENENET NOTE: This is incomplete |
| using System.Threading; |
| |
| namespace Lucene.Net.Util |
| { |
| |
| |
| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| /// <summary> |
| /// A <seealso cref="SecurityManager"/> that prevents tests calling <seealso cref="System#exit(int)"/>. |
| /// Only the test runner itself is allowed to exit the JVM. |
| /// All other security checks are handled by the default security policy. |
| /// <p> |
| /// Use this with {@code -Djava.security.manager=Lucene.Net.Util.TestSecurityManager}. |
| /// </summary> |
| public sealed class TestSecurityManager : SecurityManager |
| { |
| |
| internal const string TEST_RUNNER_PACKAGE = "com.carrotsearch.ant.tasks.junit4."; |
| |
| /// <summary> |
| /// Creates a new TestSecurityManager. this ctor is called on JVM startup, |
| /// when {@code -Djava.security.manager=Lucene.Net.Util.TestSecurityManager} |
| /// is passed to JVM. |
| /// </summary> |
| public TestSecurityManager() : base() |
| { |
| } |
| |
| /// <summary> |
| /// {@inheritDoc} |
| /// <p>this method inspects the stack trace and checks who is calling |
| /// <seealso cref="System#exit(int)"/> and similar methods </summary> |
| /// <exception cref="SecurityException"> if the caller of this method is not the test runner itself. </exception> |
| public override void CheckExit(int status) |
| { |
| AccessController.doPrivileged(new PrivilegedActionAnonymousInnerClassHelper(this, status)); |
| |
| // we passed the stack check, delegate to super, so default policy can still deny permission: |
| base.CheckExit(status); |
| } |
| |
| private class PrivilegedActionAnonymousInnerClassHelper : PrivilegedAction<Void> |
| { |
| private readonly TestSecurityManager OuterInstance; |
| |
| private int Status; |
| |
| public PrivilegedActionAnonymousInnerClassHelper(TestSecurityManager outerInstance, int status) |
| { |
| this.OuterInstance = outerInstance; |
| this.Status = status; |
| } |
| |
| public override void Run() |
| { |
| const string systemClassName = typeof(System).Name, runtimeClassName = typeof(Runtime).Name; |
| string exitMethodHit = null; |
| foreach (StackTraceElement se in Thread.CurrentThread.StackTrace) |
| { |
| const string className = se.ClassName, methodName = se.MethodName; |
| if (("exit".Equals(methodName) || "halt".Equals(methodName)) && (systemClassName.Equals(className) || runtimeClassName.Equals(className))) |
| { |
| exitMethodHit = className + '#' + methodName + '(' + Status + ')'; |
| continue; |
| } |
| |
| if (exitMethodHit != null) |
| { |
| if (className.StartsWith(TEST_RUNNER_PACKAGE)) |
| { |
| // this exit point is allowed, we return normally from closure: |
| return null; //void |
| } |
| else |
| { |
| // anything else in stack trace is not allowed, break and throw SecurityException below: |
| break; |
| } |
| } |
| } |
| |
| if (exitMethodHit == null) |
| { |
| // should never happen, only if JVM hides stack trace - replace by generic: |
| exitMethodHit = "JVM exit method"; |
| } |
| throw new SecurityException(exitMethodHit + " calls are not allowed because they terminate the test runner's JVM."); |
| } |
| } |
| |
| } |
| |
| } |
| #endif |