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) ======================================================================
|