Name: nt126004 Date: 01/28/2003
FULL PRODUCT VERSION :
Command-line version info:
java version "1.3.1_04"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.1_04-b02)
Java HotSpot(TM) Client VM (build 1.3.1_04-b02, mixed mode)
Java WebStart version info:
Java Web Start 1.2 Console, started Thu Dec 26 12:48:11 CST 2002
Java 2 Runtime Environment: Version 1.3.1_04 by Sun Microsystems Inc.
FULL OPERATING SYSTEM VERSION :
Microsoft Windows XP [Version 5.1.2600]
EXTRA RELEVANT SYSTEM CONFIGURATION :
Java Webstart 1.2 (also seen in 1.0.1)
A DESCRIPTION OF THE PROBLEM :
Our application gets a java.security.AccessControlException
when running from Java WebStart. It successfully runs when
started from the command line (with null SecurityManager).
The jar files are signed and the jnlp file requests
all-permissions. Java WebStart starts executing the
application, but it quickly stops with the exception.
This a command-line JMS client application using the BEA
WebLogic 7.0SP1 jar files to talk to BEA's JMS
implementation. This is just a simple utility that
demonstrates a general problem using BEA's WLS 7.0SP1
libraries with java webstart.
We see this bug with Java WebStart 1.0.1_01 also.
(Please see comments)
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. build app
2. jar it up
3. sign app jar and weblogic WLS 7.0SP1 jar file
4. install on web server with .jnlp file shown
5. launch w/ web browser (using java webstart) and see exception
EXPECTED VERSUS ACTUAL BEHAVIOR :
Application should successfully initialize.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
java.security.AccessControlException: access denied (java.lang.RuntimePermission
getClassLoader)
at java.security.AccessControlContext.checkPermission(Unknown Source)
at java.security.AccessController.checkPermission(Unknown Source)
at java.lang.SecurityManager.checkPermission(Unknown Source)
at java.lang.ClassLoader.getParent(Unknown Source)
at
weblogic.rmi.internal.ClientRuntimeDescriptor.computeInterfaces(ClientRuntimeDescriptor.java:253)
at
weblogic.rmi.internal.ClientRuntimeDescriptor.intern(ClientRuntimeDescriptor.java:123)
at weblogic.rmi.internal.StubInfo.readObject(StubInfo.java:100)
at java.lang.reflect.Method.invoke(Native Method)
at java.io.ObjectInputStream.invokeObjectReader(Unknown Source)
at java.io.ObjectInputStream.inputObject(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at
weblogic.common.internal.ChunkedObjectInputStream.readObject(ChunkedObjectInputStream.java:140)
at
weblogic.jms.client.JMSConnectionFactory.readExternal(JMSConnectionFactory.java:173)
at
weblogic.common.internal.ChunkedObjectInputStream.readObject(ChunkedObjectInputStream.java:131)
at weblogic.rjvm.MsgAbbrevInputStream.readObject(MsgAbbrevInputStream.java:91)
at weblogic.rmi.internal.ObjectIO.readObject(ObjectIO.java:56)
at weblogic.rjvm.ResponseImpl.unmarshalReturn(ResponseImpl.java:161)
at
weblogic.rmi.cluster.ReplicaAwareRemoteRef.invoke(ReplicaAwareRemoteRef.java:263)
at
weblogic.rmi.cluster.ReplicaAwareRemoteRef.invoke(ReplicaAwareRemoteRef.java:229)
at weblogic.jndi.internal.ServerNamingNode_WLStub.lookup(Unknown Source)
at weblogic.jndi.internal.WLContextImpl.lookup(WLContextImpl.java:337)
at weblogic.jndi.internal.WLContextImpl.lookup(WLContextImpl.java:332)
at javax.naming.InitialContext.lookup(Unknown Source)
at com.ti.mtc.facops.util.TopicDump.init(TopicDump.java:113)
at com.ti.mtc.facops.util.TopicDump.<init>(TopicDump.java:107)
at com.ti.mtc.facops.util.TopicDump.main(TopicDump.java:91)
at java.lang.reflect.Method.invoke(Native Method)
at com.sun.javaws.Launcher.executeApplication(Unknown Source)
at com.sun.javaws.Launcher.executeMainClass(Unknown Source)
at com.sun.javaws.Launcher.continueLaunch(Unknown Source)
at com.sun.javaws.Launcher.handleApplicationDesc(Unknown Source)
at com.sun.javaws.Launcher.handleLaunchFile(Unknown Source)
at com.sun.javaws.Launcher.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
// see comments section
/** This class will create connections to a JMS topic and dump the messages
being distributed.
*/
package com.ti.mtc.facops.util;
import java.util.*;
import javax.naming.*;
import javax.jms.*;
public class TopicDump
implements MessageListener, ExceptionListener
{
private static final java.text.DateFormat DATE_FORMAT =
new java.text.SimpleDateFormat("yyyy/MM/dd kk:mm:ss.SSS");
static final String JMS_FACTORY="javax.jms.TopicConnectionFactory";
private TopicConnectionFactory conFactory;
private TopicConnection con;
private TopicSession session;
private TopicSubscriber consumer;
private Topic destination;
/** Run the program
* @param args 0: JNDI name of destination
*/
public static void main(String args[]) throws Exception {
// Command-line processing. Ick, isn't there a class to do this?
int argIndex; // This will point to first arg after optoins
/** optional message selector */
String selector = null;
/** required JNDI name for Destination we'll read from */
String jndiName = null;
final String USAGE_STRING = "TopicDump [-selector selector] jndiName";
try {
for (argIndex = 0; argIndex < args.length; argIndex++) {
String arg = args[argIndex];
String argParm = (argIndex + 1 < args.length) ?
args[argIndex + 1] : null;
// We're outta here if not an option
if (!arg.startsWith("-")) {
break;
}
// Consume a -- end-of-args marker and exit
if (arg.equals("--")) {
argIndex++;
break;
}
// Series of if/else if/else if... for the args we understand
// Manually advance argIndex if an argParm is consumed
if (arg.equals("-selector") && argParm != null) {
// optional message selector
selector = argParm;
argIndex++;
}
// Other "else if" checks above here, end with this error "else"
else {
throw new Exception("Error parsing option \""
+ args[argIndex] + "\"");
}
}
/* Set up for pre-increments next.
* That's useful so argIndex points to bad arg if we get exception.
*/
argIndex--;
try {
jndiName = args[++argIndex];
} catch (Exception e) {
throw new Exception("Exception " + e.getClass()
+ " parsing required parameter \""
+ ((argIndex < args.length) ? args[argIndex] : "(empty)")
+ "\"\n" + e);
}
// At the end, make sure there are no extra parameters
if (argIndex + 1 < args.length) {
throw new Exception("Ignoring extra parameters, \"" +
args[argIndex + 1] + "\" and after");
}
} catch (Exception e) {
throw new Exception(USAGE_STRING + "\n" + e.getMessage());
}
TopicDump d = new TopicDump(jndiName, selector);
if (true) {
d.dumpAsynchronously();
// Wait forever
synchronized (d) {
d.wait();
}
}
else {
d.dumpMessages();
}
d.close();
}
public TopicDump(String jndiName, String selector) throws Exception {
InitialContext ic = new InitialContext();
init(ic, jndiName, selector);
}
/** Initialize JMS topic connection */
private void init(Context ctx, String name, String selector)
throws NamingException, JMSException {
conFactory = (TopicConnectionFactory)ctx.lookup(JMS_FACTORY);
con = conFactory.createTopicConnection();
session = con.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
destination = (Topic)ctx.lookup(name);
con.setExceptionListener(this);
// Create a consumer with the selector (if specified)
// "noLocal" option isn't interesting as we don't publish, set false
consumer = (selector == null) ?
session.createSubscriber(destination) :
session.createSubscriber(destination, selector, false);
con.start();
}
/** Register us for async callback on message availability */
void dumpAsynchronously() throws JMSException {
consumer.setMessageListener(this);
}
/** Dump out messages. Exit when empty */
void dumpMessages() throws Exception {
while (true) {
Message m;
// If no messages available, break out
m = consumer.receiveNoWait();
if (m == null) {
break;
}
// Process the message
onMessage(m);
}
}
/**
* Closes JMS objects
*/
public void close() {
// silently ignore all exceptions
try {consumer.close();} catch (Exception e) {};
try {session.close();} catch (Exception e) {};
try {con.close();} catch (Exception e) {};
}
/** Called automatically (or by us) on receipt of a message.
*/
public void onMessage(javax.jms.Message msg) {
try {
String msgText;
if (msg instanceof TextMessage) {
msgText = ((TextMessage)msg).getText();
} else if (msg instanceof ObjectMessage) {
msgText = ((ObjectMessage)msg).getObject().toString();
} else {
msgText = msg.toString();
}
StringBuffer sb = new StringBuffer(8192);
sb.append("Message: id=").append(msg.getJMSMessageID());
sb.append(" corr=").append(msg.getJMSCorrelationID());
sb.append(" dest=").append(msg.getJMSDestination());
sb.append(" reply=").append(msg.getJMSReplyTo());
sb.append(" ts=").append(DATE_FORMAT.format(new Date(msg.getJMSTimestamp())));
System.out.println(sb.toString());
sb = new StringBuffer(8192);
sb.append("Properties:");
for (Enumeration e = msg.getPropertyNames();
e.hasMoreElements(); ) {
String propName = (String)e.nextElement();
sb.append(' ').append(propName).append('=');
sb.append(msg.getObjectProperty(propName));
}
System.out.println(sb.toString());
System.out.println(msgText);
System.out.println("");
} catch (Exception e) {
e.printStackTrace(System.err);
}
}
public void onException(JMSException e) {
e.printStackTrace(System.err);
close();
// Wake us from the wait
synchronized (this) {
this.notifyAll();
}
}
}
Here's the .jnlp file
<?xml version="1.0" encoding="UTF-8"?>
<jnlp spec="1.0+"
codebase="http://www.mtc.ti.com/applications/facops/whiteboard/javaws/test"
href="TopicDump-neptune7001.jnlp">
<information>
<title>TopicDump</title>
<vendor>Texas Instruments</vendor>
<homepage href="http://www.mtc.ti.com/~jmaline/"/>
<description>help me understand Java WebStart security</description>
<description kind="short">security check</description>
<offline-allowed/>
</information>
<resources>
<j2se version="1.3"/>
<jar href="facops.jar"/>
<jar href="../wli70sp1/weblogic.jar"/>
<property name="java.naming.factory.initial"
value="weblogic.jndi.WLInitialContextFactory"/>
<property name="java.naming.provider.url"
value="t3://neptune.mtc.ti.com:7001"/>
</resources>
<security>
<all-permissions/>
</security>
<application-desc main-class="com.ti.mtc.facops.util.TopicDump">
<argument>com.bea.wlpi.AuditTopic</argument>
</application-desc>
</jnlp>
---------- END SOURCE ----------
CUSTOMER WORKAROUND :
Edit jre\lib\security\java.policy files on client to grant
the following:
permission java.lang.RuntimePermission "getClassLoader";
This is unsatisfying since it requires touching all the
client computers. Plus I'm not sure if security
implications of granting this.
This is BEA's recommended workaround.
(Review ID: 179436)
======================================================================