001: /*
002: * This file is part of the WfMOpen project.
003: * Copyright (C) 2001-2003 Danet GmbH (www.danet.de), GS-AN.
004: * All rights reserved.
005: *
006: * This program is free software; you can redistribute it and/or modify
007: * it under the terms of the GNU General Public License as published by
008: * the Free Software Foundation; either version 2 of the License, or
009: * (at your option) any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: * GNU General Public License for more details.
015: *
016: * You should have received a copy of the GNU General Public License
017: * along with this program; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: *
020: * $Id: EJBClientTest.java,v 1.3 2006/09/29 12:32:11 drmlipp Exp $
021: *
022: * $Log: EJBClientTest.java,v $
023: * Revision 1.3 2006/09/29 12:32:11 drmlipp
024: * Consistently using WfMOpen as projct name now.
025: *
026: * Revision 1.2 2004/09/10 10:46:14 drmlipp
027: * Added new usage pattern.
028: *
029: * Revision 1.1.1.1 2003/12/19 13:01:37 drmlipp
030: * Updated to 1.1rc1
031: *
032: * Revision 1.2 2003/11/19 12:40:25 lipp
033: * Improved by deriving from decorator (results in better display in
034: * GUI).
035: *
036: * Revision 1.1 2003/10/21 21:00:45 lipp
037: * Moved EJBClientTest to new junit sub-package.
038: *
039: * Revision 1.1 2003/08/27 11:49:51 lipp
040: * Initial version.
041: *
042: */
043: package de.danet.an.util.junit;
044:
045: import java.lang.reflect.InvocationTargetException;
046: import java.lang.reflect.Method;
047: import java.security.PrivilegedAction;
048:
049: import javax.security.auth.Subject;
050: import javax.security.auth.login.LoginContext;
051:
052: import junit.extensions.TestDecorator;
053: import junit.framework.Test;
054: import junit.framework.TestResult;
055:
056: /**
057: * This class provides a wrapper around a JUnit test that will run the
058: * test as the subject identified by <code>LoginContext</code> passed
059: * to the constructor. <P>
060: *
061: * The operations performed depend on the context. The default is to
062: * simply forward the call to <code>run</code> to the
063: * <code>Test</code> passed to the constructor.<P>
064: *
065: * If, however, the class <code>weblogic.security.Security</code> is
066: * available, the test will be passed to its <code>runAs</code>
067: * method.<P>
068: *
069: * While the usage of the test decorator pattern is straightforward,
070: * it imposes some problems when an individual test is to be run in an
071: * interactive invironment like Eclipse. There, you can select a test
072: * class, but you cannot choose to run this test class only after
073: * wrapping it in a decorator.<P>
074: *
075: * As an alternative usage pattern, you can therefore override the
076: * <code>run</code> method of your test class. This is not trivial, as
077: * <code>EJBClientTest.run</code> must call the <code>super.run</code>
078: * of your test class:<pre>
079: * /**
080: * * Runs the tests with an appropriate login context.
081: * *
082: * * @param testResult a <code>TestResult</code> value
083: * */
084: * public void run(final TestResult testResult) {
085: * EJBClientTest.run (new Runnable () {
086: * public void run () {
087: * ProcLifeCycle.super.run (testResult);
088: * }
089: * }, loginContext, testResult);
090: * }</pre>
091: *
092: * @author <a href="mailto:lipp@danet.de"></a>
093: * @version $Revision: 1.3 $
094: */
095:
096: public class EJBClientTest extends TestDecorator {
097:
098: private LoginContext loginContext;
099:
100: /**
101: * Creates an instance of <code>EJBClientTest</code>
102: * with all attributes initialized to the given values.
103: * @param ctx a <code>LoginContext</code>
104: * @param test a <code>Test</code>
105: */
106: public EJBClientTest(LoginContext ctx, Test test) {
107: super (test);
108: loginContext = ctx;
109: }
110:
111: /**
112: * Runs the test passed to the constructor as described in the
113: * class comment.
114: *
115: * @param testResult a <code>TestResult</code> value
116: */
117: public void run(final TestResult testResult) {
118: run(new Runnable() {
119: public void run() {
120: getTest().run(testResult);
121: }
122: }, loginContext, testResult);
123: }
124:
125: /**
126: * Runs the test passed in with the given login context.
127: *
128: * @param test the test to run
129: * @param loginContext the login context to use
130: * @param testResult a <code>TestResult</code> value
131: */
132: public static void run(final Runnable test,
133: LoginContext loginContext, final TestResult testResult) {
134: Class wlsSec = null;
135: try {
136: wlsSec = Thread.currentThread().getContextClassLoader()
137: .loadClass("weblogic.security.Security");
138: } catch (ClassNotFoundException e) {
139: // OK, not WLS client
140: }
141: if (wlsSec != null) {
142: try {
143: Class[] ats = new Class[] { Subject.class,
144: PrivilegedAction.class };
145: Method m = wlsSec.getMethod("runAs", ats);
146: Object[] args = new Object[] {
147: loginContext.getSubject(),
148: new PrivilegedAction() {
149: public Object run() {
150: test.run();
151: return null;
152: }
153: } };
154: m.invoke(null, args);
155: } catch (NoSuchMethodException e) {
156: throw new IllegalStateException(e.getMessage());
157: } catch (SecurityException e) {
158: throw new IllegalStateException(e.getMessage());
159: } catch (IllegalAccessException e) {
160: throw new IllegalStateException(e.getMessage());
161: } catch (InvocationTargetException e) {
162: throw new IllegalStateException(e.getTargetException()
163: .getMessage());
164: }
165: } else {
166: test.run();
167: }
168: }
169: }
|