8051422: Remove JNDI dependency on java.applet.Applet

Reviewed-by: alanb, chegar
This commit is contained in:
Pavel Rappo 2014-07-28 16:24:38 +01:00
parent 924b9f9fde
commit 5a7fabe3e0
8 changed files with 136 additions and 138 deletions

View File

@ -165,6 +165,7 @@ public class CorbaUtils {
// Get Applet from environment // Get Applet from environment
if (env != null) { if (env != null) {
@SuppressWarnings("deprecation")
Applet applet = (Applet) env.get(Context.APPLET); Applet applet = (Applet) env.get(Context.APPLET);
if (applet != null) { if (applet != null) {
// Create ORBs using applet and orbProp // Create ORBs using applet and orbProp

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -28,8 +28,6 @@ package com.sun.naming.internal;
import java.io.InputStream; import java.io.InputStream;
import java.io.IOException; import java.io.IOException;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.Map; import java.util.Map;
@ -126,52 +124,6 @@ public final class ResourceManager {
private static final WeakReference<Object> NO_FACTORY = private static final WeakReference<Object> NO_FACTORY =
new WeakReference<>(null); new WeakReference<>(null);
/**
* A class to allow JNDI properties be specified as applet parameters
* without creating a static dependency on java.applet.
*/
private static class AppletParameter {
private static final Class<?> clazz = getClass("java.applet.Applet");
private static final Method getMethod =
getMethod(clazz, "getParameter", String.class);
private static Class<?> getClass(String name) {
try {
return Class.forName(name, true, null);
} catch (ClassNotFoundException e) {
return null;
}
}
private static Method getMethod(Class<?> clazz,
String name,
Class<?>... paramTypes)
{
if (clazz != null) {
try {
return clazz.getMethod(name, paramTypes);
} catch (NoSuchMethodException e) {
throw new AssertionError(e);
}
} else {
return null;
}
}
/**
* Returns the value of the applet's named parameter.
*/
static Object get(Object applet, String name) {
// if clazz is null then applet cannot be an Applet.
if (clazz == null || !clazz.isInstance(applet))
throw new ClassCastException(applet.getClass().getName());
try {
return getMethod.invoke(applet, name);
} catch (InvocationTargetException |
IllegalAccessException e) {
throw new AssertionError(e);
}
}
}
// There should be no instances of this class. // There should be no instances of this class.
private ResourceManager() { private ResourceManager() {
} }
@ -179,12 +131,11 @@ public final class ResourceManager {
// ---------- Public methods ---------- // ---------- Public methods ----------
/* /**
* Given the environment parameter passed to the initial context * Given the environment parameter passed to the initial context
* constructor, returns the full environment for that initial * constructor, returns the full environment for that initial
* context (never null). This is based on the environment * context (never null). This is based on the environment
* parameter, the applet parameters (where appropriate), the * parameter, the system properties, and all application resource files.
* system properties, and all application resource files.
* *
* <p> This method will modify <tt>env</tt> and save * <p> This method will modify <tt>env</tt> and save
* a reference to it. The caller may no longer modify it. * a reference to it. The caller may no longer modify it.
@ -196,18 +147,16 @@ public final class ResourceManager {
* resource file * resource file
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static Hashtable<?, ?> getInitialEnvironment( public static Hashtable<?, ?> getInitialEnvironment(Hashtable<?, ?> env)
Hashtable<?, ?> env)
throws NamingException throws NamingException
{ {
String[] props = VersionHelper.PROPS; // system/applet properties String[] props = VersionHelper.PROPS; // system properties
if (env == null) { if (env == null) {
env = new Hashtable<>(11); env = new Hashtable<>(11);
} }
Object applet = env.get(Context.APPLET);
// Merge property values from env param, applet params, and system // Merge property values from env param, and system properties.
// properties. The first value wins: there's no concatenation of // The first value wins: there's no concatenation of
// colon-separated lists. // colon-separated lists.
// Read system properties by first trying System.getProperties(), // Read system properties by first trying System.getProperties(),
// and then trying System.getProperty() if that fails. The former // and then trying System.getProperty() if that fails. The former
@ -217,18 +166,13 @@ public final class ResourceManager {
for (int i = 0; i < props.length; i++) { for (int i = 0; i < props.length; i++) {
Object val = env.get(props[i]); Object val = env.get(props[i]);
if (val == null) { if (val == null) {
if (applet != null) { // Read system property.
val = AppletParameter.get(applet, props[i]); val = (jndiSysProps != null)
}
if (val == null) {
// Read system property.
val = (jndiSysProps != null)
? jndiSysProps[i] ? jndiSysProps[i]
: helper.getJndiProperty(i); : helper.getJndiProperty(i);
} }
if (val != null) { if (val != null) {
((Hashtable<String, Object>)env).put(props[i], val); ((Hashtable<String, Object>)env).put(props[i], val);
}
} }
} }
@ -248,8 +192,8 @@ public final class ResourceManager {
/** /**
* Retrieves the property from the environment, or from the provider * Retrieves the property from the environment, or from the provider
* resource file associated with the given context. The environment * resource file associated with the given context. The environment
* may in turn contain values that come from applet parameters, * may in turn contain values that come from system properties,
* system properties, or application resource files. * or application resource files.
* *
* If <tt>concat</tt> is true and both the environment and the provider * If <tt>concat</tt> is true and both the environment and the provider
* resource file contain the property, the two values are concatenated * resource file contain the property, the two values are concatenated
@ -289,7 +233,7 @@ public final class ResourceManager {
* property. * property.
* *
* The property is gotten from the environment and the provider * The property is gotten from the environment and the provider
* resource file associated with the given context and concantenated. * resource file associated with the given context and concatenated.
* See getProperty(). The resulting property value is a list of class names. * See getProperty(). The resulting property value is a list of class names.
*<p> *<p>
* This method then loads each class using the current thread's context * This method then loads each class using the current thread's context

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -203,9 +203,7 @@ import java.util.Hashtable;
* <h2>Application Resource Files</h2> * <h2>Application Resource Files</h2>
* *
* When an application is deployed, it will generally have several * When an application is deployed, it will generally have several
* codebase directories and JARs in its classpath. Similarly, when an * codebase directories and JARs in its classpath. JNDI locates (using
* applet is deployed, it will have a codebase and archives specifying
* where to find the applet's classes. JNDI locates (using
* {@link ClassLoader#getResources <tt>ClassLoader.getResources()</tt>}) * {@link ClassLoader#getResources <tt>ClassLoader.getResources()</tt>})
* all <em>application resource files</em> named <tt>jndi.properties</tt> * all <em>application resource files</em> named <tt>jndi.properties</tt>
* in the classpath. * in the classpath.
@ -236,7 +234,7 @@ import java.util.Hashtable;
* *
* When JNDI constructs an initial context, the context's environment * When JNDI constructs an initial context, the context's environment
* is initialized with properties defined in the environment parameter * is initialized with properties defined in the environment parameter
* passed to the constructor, the system properties, the applet parameters, * passed to the constructor, the system properties,
* and the application resource files. See * and the application resource files. See
* <a href=InitialContext.html#ENVIRONMENT><tt>InitialContext</tt></a> * <a href=InitialContext.html#ENVIRONMENT><tt>InitialContext</tt></a>
* for details. * for details.
@ -268,8 +266,8 @@ import java.util.Hashtable;
* <p> * <p>
* In this way, each service provider developer can specify a list of * In this way, each service provider developer can specify a list of
* factories to use with that service provider. These can be modified by * factories to use with that service provider. These can be modified by
* the application resources specified by the deployer of the application * the application resources specified by the deployer of the application,
* or applet, which in turn can be modified by the user. * which in turn can be modified by the user.
* *
* @author Rosanna Lee * @author Rosanna Lee
* @author Scott Seligman * @author Scott Seligman
@ -822,7 +820,7 @@ public interface Context {
* of the property should be the fully qualified class name * of the property should be the fully qualified class name
* of the factory class that will create an initial context. * of the factory class that will create an initial context.
* This property may be specified in the environment parameter * This property may be specified in the environment parameter
* passed to the initial context constructor, an applet parameter, * passed to the initial context constructor,
* a system property, or an application resource file. * a system property, or an application resource file.
* If it is not specified in any of these sources, * If it is not specified in any of these sources,
* <tt>NoInitialContextException</tt> is thrown when an initial * <tt>NoInitialContextException</tt> is thrown when an initial
@ -837,7 +835,6 @@ public interface Context {
* @see NoInitialContextException * @see NoInitialContextException
* @see #addToEnvironment(String, Object) * @see #addToEnvironment(String, Object)
* @see #removeFromEnvironment(String) * @see #removeFromEnvironment(String)
* @see #APPLET
*/ */
String INITIAL_CONTEXT_FACTORY = "java.naming.factory.initial"; String INITIAL_CONTEXT_FACTORY = "java.naming.factory.initial";
@ -847,8 +844,8 @@ public interface Context {
* of the property should be a colon-separated list of the fully * of the property should be a colon-separated list of the fully
* qualified class names of factory classes that will create an object * qualified class names of factory classes that will create an object
* given information about the object. * given information about the object.
* This property may be specified in the environment, an applet * This property may be specified in the environment, a system property,
* parameter, a system property, or one or more resource files. * or one or more resource files.
* *
* <p> The value of this constant is "java.naming.factory.object". * <p> The value of this constant is "java.naming.factory.object".
* *
@ -856,7 +853,6 @@ public interface Context {
* @see javax.naming.spi.ObjectFactory * @see javax.naming.spi.ObjectFactory
* @see #addToEnvironment(String, Object) * @see #addToEnvironment(String, Object)
* @see #removeFromEnvironment(String) * @see #removeFromEnvironment(String)
* @see #APPLET
*/ */
String OBJECT_FACTORIES = "java.naming.factory.object"; String OBJECT_FACTORIES = "java.naming.factory.object";
@ -866,8 +862,8 @@ public interface Context {
* of the property should be a colon-separated list of the fully * of the property should be a colon-separated list of the fully
* qualified class names of state factory classes that will be used * qualified class names of state factory classes that will be used
* to get an object's state given the object itself. * to get an object's state given the object itself.
* This property may be specified in the environment, an applet * This property may be specified in the environment, a system property,
* parameter, a system property, or one or more resource files. * or one or more resource files.
* *
* <p> The value of this constant is "java.naming.factory.state". * <p> The value of this constant is "java.naming.factory.state".
* *
@ -875,7 +871,6 @@ public interface Context {
* @see javax.naming.spi.StateFactory * @see javax.naming.spi.StateFactory
* @see #addToEnvironment(String, Object) * @see #addToEnvironment(String, Object)
* @see #removeFromEnvironment(String) * @see #removeFromEnvironment(String)
* @see #APPLET
* @since 1.3 * @since 1.3
*/ */
String STATE_FACTORIES = "java.naming.factory.state"; String STATE_FACTORIES = "java.naming.factory.state";
@ -887,9 +882,8 @@ public interface Context {
* of the property should be a colon-separated list of package * of the property should be a colon-separated list of package
* prefixes for the class name of the factory class that will create * prefixes for the class name of the factory class that will create
* a URL context factory. * a URL context factory.
* This property may be specified in the environment, * This property may be specified in the environment, a system property,
* an applet parameter, a system property, or one or more * or one or more resource files.
* resource files.
* The prefix <tt>com.sun.jndi.url</tt> is always appended to * The prefix <tt>com.sun.jndi.url</tt> is always appended to
* the possibly empty list of package prefixes. * the possibly empty list of package prefixes.
* *
@ -900,8 +894,7 @@ public interface Context {
* @see javax.naming.spi.ObjectFactory * @see javax.naming.spi.ObjectFactory
* @see #addToEnvironment(String, Object) * @see #addToEnvironment(String, Object)
* @see #removeFromEnvironment(String) * @see #removeFromEnvironment(String)
* @see #APPLET */
*/
String URL_PKG_PREFIXES = "java.naming.factory.url.pkgs"; String URL_PKG_PREFIXES = "java.naming.factory.url.pkgs";
/** /**
@ -909,8 +902,8 @@ public interface Context {
* for specifying configuration information for the service provider * for specifying configuration information for the service provider
* to use. The value of the property should contain a URL string * to use. The value of the property should contain a URL string
* (e.g. "ldap://somehost:389"). * (e.g. "ldap://somehost:389").
* This property may be specified in the environment, * This property may be specified in the environment, a system property,
* an applet parameter, a system property, or a resource file. * or a resource file.
* If it is not specified in any of these sources, * If it is not specified in any of these sources,
* the default configuration is determined by the service provider. * the default configuration is determined by the service provider.
* *
@ -918,7 +911,6 @@ public interface Context {
* *
* @see #addToEnvironment(String, Object) * @see #addToEnvironment(String, Object)
* @see #removeFromEnvironment(String) * @see #removeFromEnvironment(String)
* @see #APPLET
*/ */
String PROVIDER_URL = "java.naming.provider.url"; String PROVIDER_URL = "java.naming.provider.url";
@ -926,8 +918,8 @@ public interface Context {
* Constant that holds the name of the environment property * Constant that holds the name of the environment property
* for specifying the DNS host and domain names to use for the * for specifying the DNS host and domain names to use for the
* JNDI URL context (for example, "dns://somehost/wiz.com"). * JNDI URL context (for example, "dns://somehost/wiz.com").
* This property may be specified in the environment, * This property may be specified in the environment, a system property,
* an applet parameter, a system property, or a resource file. * or a resource file.
* If it is not specified in any of these sources * If it is not specified in any of these sources
* and the program attempts to use a JNDI URL containing a DNS name, * and the program attempts to use a JNDI URL containing a DNS name,
* a <tt>ConfigurationException</tt> will be thrown. * a <tt>ConfigurationException</tt> will be thrown.
@ -1073,27 +1065,25 @@ public interface Context {
String LANGUAGE = "java.naming.language"; String LANGUAGE = "java.naming.language";
/** /**
* Constant that holds the name of the environment property for * @deprecated An environment property with this name is ignored
* specifying an applet for the initial context constructor to use * while constructing an initial context.
* when searching for other properties. * This constant was originally used as a property name to specify an
* The value of this property is the * {@code Applet} to retrieve parameters from, when creating an initial
* <tt>java.applet.Applet</tt> instance that is being executed. * context. Currently any applet properties that need to be passed to an
* This property may be specified in the environment parameter * initial context should be copied into the environment hashtable:
* passed to the initial context constructor. * <pre>{@code
* When this property is set, each property that the initial context * Hashtable env = new Hashtable();
* constructor looks for in the system properties is first looked for * env.put(Context.INITIAL_CONTEXT_FACTORY,
* in the applet's parameter list. * ((Applet) this).getParameter(Context.INITIAL_CONTEXT_FACTORY));
* If this property is unspecified, the initial context constructor * env.put(Context.PROVIDER_URL,
* will search for properties only in the environment parameter * ((Applet) this).getParameter(Context.PROVIDER_URL));
* passed to it, the system properties, and application resource files. * // ... other properties ...
* *
* <p> The value of this constant is "java.naming.applet". * Context ctx = new InitialContext(env);
* * }</pre>
* @see #addToEnvironment(String, Object)
* @see #removeFromEnvironment(String)
* @see InitialContext
* *
* @since 1.3 * @since 1.3
*/ */
@Deprecated
String APPLET = "java.naming.applet"; String APPLET = "java.naming.applet";
}; };

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -41,21 +41,13 @@ import com.sun.naming.internal.ResourceManager;
* is initialized with properties defined in the environment parameter * is initialized with properties defined in the environment parameter
* passed to the constructor, and in any * passed to the constructor, and in any
* <a href=Context.html#RESOURCEFILES>application resource files</a>. * <a href=Context.html#RESOURCEFILES>application resource files</a>.
* In addition, a small number of standard JNDI properties may
* be specified as system properties or as applet parameters
* (through the use of {@link Context#APPLET}).
* These special properties are listed in the field detail sections of the
* <a href=Context.html#field_detail><tt>Context</tt></a> and
* <a href=ldap/LdapContext.html#field_detail><tt>LdapContext</tt></a>
* interface documentation.
*<p> *<p>
* JNDI determines each property's value by merging * JNDI determines each property's value by merging
* the values from the following two sources, in order: * the values from the following two sources, in order:
* <ol> * <ol>
* <li> * <li>
* The first occurrence of the property from the constructor's * The first occurrence of the property from the constructor's
* environment parameter and (for appropriate properties) the applet * environment parameter and system properties.
* parameters and system properties.
* <li> * <li>
* The application resource files (<tt>jndi.properties</tt>). * The application resource files (<tt>jndi.properties</tt>).
* </ol> * </ol>

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -334,8 +334,8 @@ public interface LdapContext extends DirContext {
* qualified class names of factory classes that will create a control * qualified class names of factory classes that will create a control
* given another control. See * given another control. See
* <tt>ControlFactory.getControlInstance()</tt> for details. * <tt>ControlFactory.getControlInstance()</tt> for details.
* This property may be specified in the environment, an applet * This property may be specified in the environment, a system property,
* parameter, a system property, or one or more resource files. * or one or more resource files.
*<p> *<p>
* The value of this constant is "java.naming.factory.control". * The value of this constant is "java.naming.factory.control".
* *

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -491,7 +491,7 @@ public class NamingManager {
* (e.g. "ftpURLContextFactory" for the "ftp" scheme-id), * (e.g. "ftpURLContextFactory" for the "ftp" scheme-id),
* in the package specified as follows. * in the package specified as follows.
* The <tt>Context.URL_PKG_PREFIXES</tt> environment property (which * The <tt>Context.URL_PKG_PREFIXES</tt> environment property (which
* may contain values taken from applet parameters, system properties, * may contain values taken from system properties,
* or application resource files) * or application resource files)
* contains a colon-separated list of package prefixes. * contains a colon-separated list of package prefixes.
* Each package prefix in * Each package prefix in
@ -661,8 +661,7 @@ public class NamingManager {
if (className == null) { if (className == null) {
NoInitialContextException ne = new NoInitialContextException( NoInitialContextException ne = new NoInitialContextException(
"Need to specify class name in environment or system " + "Need to specify class name in environment or system " +
"property, or as an applet parameter, or in an " + "property, or in an application resource file: " +
"application resource file: " +
Context.INITIAL_CONTEXT_FACTORY); Context.INITIAL_CONTEXT_FACTORY);
throw ne; throw ne;
} }

View File

@ -0,0 +1,73 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.naming.NoInitialContextException;
import java.util.Hashtable;
/*
* @test
* @bug 8051422
* @summary Make sure java.applet.Applet is not used as a source of
* configuration parameters for an InitialContext
*/
public class AppletIsNotUsed {
@SuppressWarnings("deprecation")
public static void main(String[] args) throws NamingException {
testWith(Context.APPLET);
testWith("java.naming.applet");
}
private static void testWith(String appletProperty) throws NamingException {
Hashtable<Object, Object> env = new Hashtable<>();
// Deliberately put java.lang.Object rather than java.applet.Applet
// if an applet was used we would see a ClassCastException down there
env.put(appletProperty, new Object());
// It's ok to instantiate InitialContext with no parameters
// and be unaware of it right until you try to use it
Context ctx = new InitialContext(env);
boolean threw = true;
try {
ctx.lookup("whatever");
threw = false;
} catch (NoInitialContextException e) {
String m = e.getMessage();
if (m == null || m.contains("applet"))
throw new RuntimeException("The exception message is incorrect", e);
} catch (Throwable t) {
throw new RuntimeException(
"The test was supposed to catch NoInitialContextException" +
" here, but caught: " + t.getClass().getName(), t);
} finally {
ctx.close();
}
if (!threw)
throw new RuntimeException("The test was supposed to catch NoInitialContextException here");
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -31,12 +31,11 @@ import javax.naming.*;
import java.util.Hashtable; import java.util.Hashtable;
public class NoApplet { public class NoApplet {
@SuppressWarnings("deprecation")
public static void main(String[] args) throws NamingException { public static void main(String[] args) throws NamingException {
Hashtable<Object,Object> env = new Hashtable<>(); Hashtable<Object,Object> env = new Hashtable<>();
env.put(Context.APPLET, new Object()); env.put(Context.APPLET, new Object());
try { Context ctxt = new InitialContext(env);
Context ctxt = new InitialContext(env); ctxt.close();
throw new RuntimeException("ClassCastException expected");
} catch (ClassCastException expected) { }
} }
} }